NDEF
在android上使用NDEF 格式的 NFC主要有两个用处:
1.读取一张NFC卡的NDEF 数据;
2.发送NDEF信息到另外一台有Android Beam的设备;
标签分发系统
一台电量充足的android设备在屏幕没有被锁的情况通常都在检索NFC标签,除非NFC被禁止使用了;
当该设备发现了一个NFC标签,被要求的行为是不经过询问用户使用哪个应用而直接用一个最合适的Activity(理解成界面)来管控这个意图。因为设备扫描NFC标签是在非常小 的范围内的,让用户手动选择一个activity可能会致使设备和卡分离从而断开连接。开发者也要避免出现多个页面让用户选择的情况
android 提供了特别的标签分发系统用来分来和解析扫描的NFC卡片,和尝试定位对扫描的卡感兴趣的应用。通过下面做到:
1.解析NFC卡片 和 辨别 卡片中标识“数据负载” 的MIME类型 或者URI;
2.封装MIMD类型或者URI和负载到intent中;
3.基于这个intent 打开一个activity;
NDEF
NDEF 的数据被封装在message(NdefMessage)中,它包含有一个或者两个记录(NdefRecord)。每一个NDEF记录一定是格式正确的,依据于你想要创建的记录类型的规格。android也支持其他不包含NDEF数据的卡片,你可以通过使用androdi.nfc.tech包中的类来使用。
当扫描一个包含NDEF格式的数据的NFC卡片时,就是解析信息和辨别MIME类型或者认证URI。在做这个之前,系统读取到NdefMessage的第一个NDEFRecord,来决定怎样去解释整个NDEF 信息(一个 NDEF信息可以有多个NDEF记录)。在一个格式正确的NDEF 信息中,第一个NdefRecord 包含下面几个字段:
1. 3-bit TNF
表明怎样解释变量长度类型字段
Table1 描述标签分发系统怎样映射TNF和类型字段 到 MIME类型或者URLs。也描述哪些TNFs 不能被映射到MIME或者URL。这些情况下,标签分发系统会落回到ACTION_TECH_DISCOVERED.
举例:如果标签分发系统遇到一个TNF_ABSOLUTE_URL类型的record,它映射record中的变量长度类型字段到一个URI.标签分发系统封装该URI到一个ACTION_NDEF_DISCOVERED intent的数据字段中,同时还有其他关于该标签的信息,像负载。另一方面,如果遇到一个TNF_UNKNOWN类型的record,将会创建一个intent,封装那个标签的技术。
2.变量长度类型
描述record 的类型,如果用的是TNF_WELL_KNOWN ,用这个字段来区分RTD(record type definition)
3.变量长度ID
record唯一的标识。这个字段不经常用,但是如果你需要唯一地识别一个卡,你可以创建一个ID给它;
4.变量长度负载
实际的你想要读取或者写入的数据负载。一个NDEF信息可以包含多个NDEF记录,所以不要假想一个写满的负荷的NDEF record是NDEFmessage的第一个。
标签分发系统使用TNF和类型字段用来映射MIME类型或者URI到NDEF 信息。如果成功,a ACTION_NDEF_DISCOVERED 的intent 中的信息,加上实际的数据负荷会封装在一起。但是,有很多种情况标签分发系统不能决定基于第一个NDEF record 数据的类型。这些情况发生于,当NDEF 数据不能映射到一个MIME或者URI,或者当一个NFC卡不由NDEF数据开头。这种情况下,标签对象关于技术和负载的信息就被封装在a ACTION_TECH_DISCOVERED
intent中。
NFC标签怎么分发到应用?
当标签分发系统完成创建一个intent,封装了NFC 标签及其标识信息,系统为这个intent过滤选出感兴趣的应用并发送。如果有超过一个应用可以管控这个intent,Activity Chooser 会展示出来让用户可以选择应用。系统定义了三个intent,从最高级到最低级优先级展示如下:
1. ACTION_NDEF_DISCOVERED :这个intent 用来打开一个Activity ,当一个包含NDEF负载的标签被扫描到和被认定是该类型。
这是最高优先级的intent,系统会尝试用这个intent在其他intent之前打开一个Activity,任何时候都可以。
2.ACTION_TECH_DISCOVERED : 如果没有activity 注册来管控ACTION_NDEF_DISCOVERED intent,系统会尝试使用该intent来打开一个应用。如果标签被扫描出包含NDEF数据不能映射到MIME类型或者URI,或者如果该标签不包含NDEF数据但是个可知的标签技术,这个intent也是直接打开(不需要先打开ACTION_NDEF_DISCOVERED )。
3.ACTION_TAG_DISCOVERED: 如果没有activity 管控前两种intent 的话,该intent将被启动。
ACTION_NDEF_DISCOVERED
To filter for ACTION_NDEF_DISCOVERED intents, declare the intent filter along with the type of data that you want to filter for. The following example filters for ACTION_NDEF_DISCOVERED intents with a MIME type of text/plain:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
The following example filters for a URI in the form of http://developer.android.com/index.html.
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html" />
</intent-filter>
ACTION_TECH_DISCOVERED 稍微复杂点
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
You can also specify multiple
tech-list
sets.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
<activity>
...
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
...
</activity>
ACTION_TAG_DISCOVERED
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
EXTRA_TAG
(required): ATag
object representing the scanned tag.EXTRA_NDEF_MESSAGES
(optional): An array of NDEF messages parsed from the tag. This extra is mandatory onACTION_NDEF_DISCOVERED
intents.EXTRA_ID
(optional): The low-level ID of the tag.
ACTION_NDEF_DISCOVERED
intent and gets the NDEF messages from an intent extra.
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
...
if (intent != null && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
Parcelable[] rawMessages =
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
NdefMessage[] messages = new NdefMessage[rawMessages.length];
for (int i = 0; i < rawMessages.length; i++) {
messages[i] = (NdefMessage) rawMessages[i];
}
// Process the messages array.
...
}
}
}
Alternatively, you can obtain a
Tag
object from the intent, which will contain the payload and allow you to enumerate the tag's technologies:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
待续……