最近在致力于NFC的开发,所以有些许体会在这里记录下来。
手机NFC离我们越来越近,虽然目前国内手机NFC还不是很普及,但是在日本手机支付已经成为一种成功的商业模式,我相信在不远的将来手机NFC周边将产生各种应用及服务,让大家的生活更加方便,更加安逸。
我们先简单了解一下NFC技术,NFC(Near Field Communication)是由RFID(免接触式射频识别)演变而来,主要应用在手机上。它的使用距离要比蓝牙要小很多,大概<=10cm,并且传输速率很低,和蓝牙比起来惨的恨,100多kbps,但是NFC天然的安全性(使用距离短,这就保证了两个终端的交互是安全的),以及建立连通快速性,这些是红外和蓝牙都无法比拟的,这也是它为什么被利用在电子支付的商业中来的原因。
其实RFID这个技术的使用很普遍,每天每个人可能都与它打交道,比如说公交卡支付、门禁系统等都使用了RFID技术。 NFC是在2004年,被Nokia, Philips和Sony提出,并在2006年Nokia推出第一款手机Nokia 6131。但是为什么NFC没有像RFID这么普及呢?我想还是和利益有关系,像NFC这样的技术其实是绕过了电信运营商这一层直接将用户和服务提供商、银行联系起来,电信运营商并没有看到利益所在,所以手机支付功能是很难通过运营商推广的,当然也不是绝对的,现在只是没有找到有效的途径解决这个问题。不过我相信运营商、应用开发商以及服务商,乃至政府都在努力解决一些问题。 android自从2.3开始支持NFC功能,iphone也将支持NFC,从这些消息我们不难看出,NFC已经得到了很多支持,估计NFC爆发指日可待。通过近期对NFC的了解,我发现其实NFC不只是在支付这条路上有前景,还有很多让NFC用户感觉到便利的地方,比如说NFC+蓝牙或NFC+Wi-Fi,这是什么意思呢,NFC作为近距离通讯,快捷方便,手机和手机或者手机与Tag只要一碰信息就可以共享,这种优势可以简化蓝牙或Wi-Fi连接复杂的操作,比如两个手机一碰,蓝牙自动配对连接,Wi-Fi Ap上贴上Tag,存储Wi-Fi的信息,手机一碰,手机自动连接这个Ap,这是多么的快捷,而且用户体验会非常好。
当然,纯依靠NFC的应用会很少,但它可以弥补一些其他技术的不足,让操作更加方便。这就靠大家都智慧来挖掘它的可用之处。
以上是我对NFC的一点点理解,接下来对android上NFC的应用进行简单分享。
NFC有两种模式,p2p和reader/writer模式,peer to peer模式是指两个终端之间通讯,reader/writer模式是指手机与NFC tags之间通讯。刚才的例子中,NFC+蓝牙就是应用p2p模式,而NFC+Wi-Fi是应用了reader/writer模式,NFC tags是一种可读写的标签,它是无源的,也就是它不耗电,很环保,而且很廉价。
对于这两种模式的在android上的使用请参照http://developer.android.com/guide/topics/nfc/index.html
如果您正致力于p2p模式的开发,我有一些小小提示,请一定要读完 “Peer to Peer Data Exchange” 这一章节其中提到的要点要理解清楚,还有当初我遇到了一个问题,是当在peer to peer 模式下如何让NFC dispatch system启动我们自己的activity?
最后我发现是在Mantifest里设置mimeType为"application/你应用的identify(我用的是包名)",如下
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <data android:mimeType="application/xxx.xxx" /> </intent-filter>
然后在push的NdefMessage里设置mimeType为"application/你应用的identify(我用的是包名)"就可以了。
package com.android.dateformat;
import java.text.DateFormat;
import java.util.Date;
public class MyDateFormat {
public String[] Months = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};
public void mydate(){
DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
long minTimestamp = 444444444;
Date date = new Date(minTimestamp);
int month = date.getMonth()+1;
for (int i = 0; i < Months.length; i++) {
if ((i+1) == month) {
date.setMonth(Integer.parseInt(Months[i]));
}
}
String MyDateStyle = dateTimeFormat.format(date);
System.out.println("日期格式:"+MyDateStyle);
System.out.println("获得月份::"+month);
}
public static void main(String[] args) {
MyDateFormat mMyDateFormat = new MyDateFormat();
mMyDateFormat.mydate();
}
}
输出异常:
Exception in thread "main" java.lang.NumberFormatException: For input string: "一月"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at com.android.dateformat.MyDateFormat.mydate(MyDateFormat.java:16)
at com.android.dateformat.MyDateFormat.main(MyDateFormat.java:26)
Android NDK的使用方法:
======================
NDK的用户提示和技巧集合
如何强制显示build命令
------------------------
执行"ndk-build V=1",实际生成的命令将会被显示。这可以用来验证你编译的东西,并且还会检查NDK的
build system中的错误。
(V=1 来自Linux内核的build system)
如何强制重新编译你的源码
------------------------
使用GNU Make的“-B”选项
ndk-build -B
如何存储本地源码到除$PROJECT/jni以外的位置:
-------------------------------------------
首先,你可以在你的$PROJECT/jni/Android.mk中包含另一个不同位置的Android.mk
另外,你需要在你的Application.mk文件中定义APP_BUILD_SCRIPT来指向那个替代的Android.mk文件
如果在不使用cd-ing的情况下来编译你的本地项目文件
------------------------------------------------
有时候,你需要在不用使用cd命令切换到根目录的情况下重新编译你的本地项目文件,可以使用
GNU-Make的'-C <path>'选项,如:
ndk-build -C <project-path>
如何将你的Application.mk文件存储子$PROJECT/jni目录之外
------------------------------------------------------
从NDK r4开始,你可以简单的将源文件放到$PROJECT/jni/目录下,然后执行'ndk-build'脚本
如果你想使用'ndk-build'命令但是将源文件放到了其他的位置,你可以使用如下命令:
ndk-build NDK_APPLICATION_MK=/path/to/your/Application.mk
如果你想使用传统的$NDK/apps/<name> 来build system,你可以创建一个符号链接到你最终的Application.mk
比如:
$PROJECT/foo/Applicatio.mk
用如下的命令创建符号链接
ln -s $PROJECT/foo $NDK/apps/<name>
这将使得你的$NDK/apps/<name>/Applicaiton.mk文件直接指向$PROJECT/jni/Application.mk
注意,这样生成的文件将仍然在$NDK/out/apps/<name>目录下。
Windows用户在使用Cygwin的情况下,它可以通过"ln -s"命令来创建符号链接,例如
ln -s <target> <link>
如何正确的添加一个包含目录到你的模块中:
--------------------------------------
如果你定义了若干模块,在编译另一个模块的时候需要包含某个模块的头文件,例如
$PROJECT/jni/foo/
Android.mk
foo.h
foo.c
$PROJECT/jni/foo/
Android.mk
fo.c
bar.c使用了"#include <foo.h>",你需要正确的将路径添加到foo模块的jni/bar/Android.mk中
例如,可以使用如下这样
LOCAL_C_INCLUDES := ../foo
但是这样是不会执行的,因为所有编译都从'ndk-build'被调用所在的目录开始,这些包含文件必须是
相对的才可以。
正确的方法是:
LOCAL_C_INCLUDE :=$(LOCAL_PATH)/../foo
它才哦那够了相对路径的方式,你需要将foo和bar移到源码目录的更深层次下。
如果你必须需要它,你可以使用NDK_APP_PROJECT_PATH指向你的项目目录
LOCAL_C_INCLUDES :=$(NDK_APP_PROJECT_PATH)/jni/foo
然而我们不建议这种方式,相对路径$(LOCAL_PATH)这种方式会更好些