NFC应用架构
当开启NFC功能,监测到附近有标签时,标签调度系统会执行: 1、解析NFC标签并搞清楚标签中标识数据负载的MIME类型或URI; 2、把MIME类型或URI以及数据负载封装到一个Intent中。 3、基于Intent来启动Activity。
开发人员需要指定自己开发的Activity所匹配的MIME类型或URI,这样标签调度系统就会调起这个Activity,并调用onNewIntent(),把Intent传过来。
声明权限
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-permission android:name="android.permission.NFC" />
指定Activity所匹配的MIME类型或URI
<activity android:name=".Activity.Main.NFCActivity">
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
处理Intent
检查NFC是否打开
public NfcAdapter NfcCheck(Activity activity) {
NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (mNfcAdapter == null) {
return null;
} else {
if (!mNfcAdapter.isEnabled()) {
Intent setNfc = new Intent(Settings.ACTION_NFC_SETTINGS);
activity.startActivity(setNfc);
}
}
return mNfcAdapter;
}
读取数据
public String readNFCFromTag(Intent intent) throws UnsupportedEncodingException {
Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawArray != null) {
NdefMessage mNdefMsg = (NdefMessage) rawArray[0];
NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
if (mNdefRecord != null) {
String readResult = new String(mNdefRecord.getPayload(), "UTF-8");
return readResult;
}
}
return "";
}
写数据
public void writeNFCToTag(String data, Intent intent) throws IOException, FormatException {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tag);
ndef.connect();
NdefRecord ndefRecord = NdefRecord.createTextRecord(null, data);
NdefRecord[] records = {ndefRecord};
NdefMessage ndefMessage = new NdefMessage(records);
ndef.writeNdefMessage(ndefMessage);
}
读取ID
public String readNFCId(Intent intent) throws UnsupportedEncodingException {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String id = ByteArrayToHexString(tag.getId());
return id;
}
要在生命周期中开启/关闭调度系统
@Override
protected void onResume() {
super.onResume();
//开启前台调度系统
mNfcAdapter.enableForegroundDispatch(this);
}
@Override
protected void onPause() {
super.onPause();
//关闭前台调度系统
mNfcAdapter.disableForegroundDispatch(this);
}
NDEF
NDEF由各种数据记录组成,而各个记录由报头(Header)和有效载荷(Payload)组成,其中NDEF记录的数据类型和大小由记录载荷的报头注明,这里的报头包含3部分,分别为Length、Type和Identifier.。 NDEF数据被封装在一个消息(NdefMessage)中,该消息中包含了一条或多条记录(NdefRecord)。 当Android设备扫描到包含NDEF格式数据的NFC标签时,它会解析该消息,并尝试搞清楚数据的MIME类型或URI标识。首先系统会读取消息(NdefMessage)中的第一条NdefRecord,来判断如何解释整个NDEF消息(一个NDEF消息能够有多条NDEF记录)。 在格式良好的NDEF消息中,第一条NdefRecord包含以下字段信息: 1、3-bit TNF(类型名称格式) 指示如何解释可变长度类型字段。 2、可变长度类型 说明记录的类型,如果使用TNF_WELL_KNOWN,那么则使用这个字段来指定记录的类型定义(RTD)。 3、可变长度ID 唯一标识该记录。这个字段不经常使用,但是,如果需要唯一的标识一个标记,那么就可以为该字段创建一个ID。 4、可变长度负载 你想读/写的实际的数据负载。一个NDEF消息能够包含多个NDEF记录,因此不要以为在NDEF消息的第一条NDEF记录中包含了所有的负载。 标签调度系统使用TNF和类型字段来尝试把MIME类型或URI映射到NDEF消息中。如果成功,它会把信息跟实际的负载一起封装到ACTION_NEDF_DISCOVERED类型的Intent中。但是,会有标签调度系统不能根据第一条NDEF记录来判断数据类型的情况,这样就会有NDEF数据不能被映射到MIME类型或URI,或者是NFC标签没有包含NDEF开始数据的情况发生。在这种情况下,就会用一个标签技术信息相关的Tag对象和封装在ACTION_TECH_DISCOVERED类型Intent对象内部的负载来代替。
三种模式
1、读卡器模式:作为非接触读卡器使用,比如从海报或者展览信息电子标签上读取相关信息。 2、点对点模式:此模式和红外线差不多,可用于数据交换,只是传输距离较短,传输创建速度较快,传输速度也快些,功耗低。 3、卡模式:这个模式其实就是相当于一张采用RFID技术的IC卡,可以替代大量的IC卡(包括信用卡)使用的场合,如商场刷卡、公交卡、门禁管制,车票,门票等等。
应用
手机读取实体卡信息
手机给实体卡充值
1、手机读取实体卡信息; 2、把实体卡信息和充值信息发送给服务器; 3、服务器返回充值成功的信息; 4、手机向实体卡写入信息。
把手机当作实体卡
需要APP开发者与公交公司达成协议。 1、POS机读取手机; 2、POS机向APP服务器发送扣款请求; 3、APP服务器向公交公司服务器执行扣款; 4、APP服务器向POS机返回扣款成功; 5、APP服务器向手机返回扣款成功。