您的位置:首页 > 其它

NFC的安卓事儿(提高篇)

2014-04-07 13:13 225 查看
(NFC基础层次的精确过滤匹配)
当你的NFC应用去扫描你配置好的标签时,你肯定不希望别的NFC应用也弹出Activity来处理,还好,标签调度系统在此进行了良好的设计。我们知道,NDEF格式规范中,数据封装在NdefMessage对象中,NdefMessage的第一个NdefRecord数据块一般用来决定其MIME类型或相应URI(当你往标签打入数据时也是要这样设计)。所以,当设备感应到标签时,标签调度系统会先分析第一个NdefRecord数据块从而决定把Intent分配给哪个应用处理。当然,如果数据的MIME类型或URI设计得不够精确,那么往往会造成匹配问题从而出现弹出多个Activity供用户选择的情况。

如何去设计良好的MIME格式呢?在这里,本人有必要先陈述下利用标签调度系统本身能完成的一些功能:

Ø 当你的设备感应到标签时你可以让设备自动调用默认浏览器打开里面的URL(一般就是一个网址)

Ø 你也可以在感应后让系统自动打开某个设备的应用程序(AAR技术,下文会讲)

Ø 你设计的过滤器和标签数据的MIME类型或URI完全匹配,那么感应后优先打开你的应用。(这就是精确匹配的问题了)

比如,你现在要往标签写入一个网址,你希望你的手机扫描后能自动打开该网址进入该网站,那么如何实现这个功能呢?在安卓官方文档里,提供了一系列创建普通NDEF数据的方法。

比如可以创建一个用TNF_ABSOLUTE_URI来解释类型的记录:

NdefRecord uriRecord = new NdefRecord(
NdefRecord.TNF_ABSOLUTE_URI, "http://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),
new byte[0], new byte[0]);
在此处,NdefRecord的第一个参数标明了如何解释数据类型,第二个参数当做是一个完整的URI,你可以写成你想设定的网址。一旦设定好你便可以把该数据块打入标签了。值得注意的是,如果你的应用有了如下过滤的配置:

<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>
那么,一旦扫描到该标签那么你的应用将作为精准匹配被优先打开,这时,只是实现了打开你应用读取数据的过程。记住,无论什么类型的记录,数据一般是存储在NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload)的最后一个参数中。如果你的过滤配置中无相应的匹配,那么扫描后系统将会试图寻找其它匹配的Activity,当无任何匹配时那么就会调用浏览器打开里面的网址了。

安卓的官方文档里更推荐另一种写入URI的方法:TNF_WELL_KNOWN解释的RTD_URI记录。这种方法更加高效(本人也没搞明白为何比较高效),你可以按照如下方式创建:

利用createUri(String)方法:

NdefRecord rtdUriRecord1 = NdefRecord.createUri("http://example.com");
也可以手动创建:

NdefRecord rtdUriRecord = new NdefRecord(
NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
其中payload保存你要设定的URI地址

显然,如果你的应用想匹配该数据的标签,那么会有如下过滤配置:

<intent-filter>
<actionandroid:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="http"
android:host="example.com"
android:pathPrefix="" />
</intent-filter>
以上便是利用URI实现精确匹配的方法,如果你在<intent-filter> 中的<data>

里面没做好相应的设定,都会造成你的应用无法实现相应过滤。比如写成如下:

<data
android:scheme="http2" //这里把http写成http2了
android:host="example.com"
android:pathPrefix="" />

那么将无法实现精准匹配了。

那么接下来我们来了解一下如何利用MIME类型实现精准匹配,MIME类型使用TNF_MIME_MEDIA来解释具体的数据类型。

MIME类型一般用来标识一些媒体信息,比如文本信息或是自己定义的格式,如以text/plain或application/x... 为开头。

你可以使用 )]createMime() 方法创建一个NdefRecord记录:

NdefRecordmimeRecord= NdefRecord.createMime(
"application/vnd.com.example.android.beam",
"Beam me up, Android".getBytes(Charset.forName("US-ASCII"))
);
或者手动地创建:

NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA ,
"application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
new byte[0],
"Beam me up, Android!".getBytes(Charset.forName("US-ASCII"))
);
一旦定义了相应类型后(如上,这里以"application/vnd.com.example.android.beam"作为一个类型来标识),那么你需要有如下过滤配置:

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/vnd.com.example.android.beam" />
</intent-filter>
一旦<intent-filter>下的<data>配置错误,同样会让你的应用在扫描后无法完成相应精确过滤,这是要始终认识到的。

上一篇介绍的写入数据的demo以文本作为示范,现在,你知道如何创建了么?对,就是这样:

NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
text.getBytes()
);
相应的过滤配置如下:

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
但这有一个问题,就是所有声明为

<data android:mimeType="text/plain" /> //表明会去处理text/plian类型的标签
的过滤的应用都能实现匹配。所以,如果你真的希望你所部属的标签只被你应用过滤那么就可以用之前那几种方法选择性的利用。

好了,关于过滤器匹配的问题就说到这里了,灵活的创建不同类型的NDEF记录是实现Activity匹配和处理的一个关键,希望能好好去掌握。下文我们将会去学习如何利用另一种匹配的技术:AAR。利用该技术我们可以在扫描标签后打开任何设定的应用程序,只不过AAR技术是和过滤匹配属于不同的层次。我们将会对此进行了解,下文再见!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: