一:NFC的tag分發系統
如果想讓android設備感應到NFC標簽,你要保證兩點
1:屏幕沒有鎖住
2:NFC功能已經在設置中打開
當系統檢測到一個NFC標簽的時候,他會自動去尋找最合適的activity去處理這個intent.
他所發出的這個Intent將會有三種action:
ACTION_NDEF_DISCOVERED:當系統檢測到tag中含有NDEF格式的數據時,且系統中有activity聲明可以接受包含NDEF數據的Intent的時候,系統會優先發出這個action的intent。
ACTION_TECH_DISCOVERED:當沒有任何一個activity聲明自己可以響應ACTION_NDEF_DISCOVERED時,系統會嘗試發出TECH的intent.即便你的tag中所包含的數據是NDEF的,但是如果這個數據的MIME type或URI不能和任何一個activity所聲明的想吻合,系統也一樣會嘗試發出tech格式的intent,而不是NDEF.
ACTION_TAG_DISCOVERED:當系統發現前兩個intent在系統中無人會接受的時候,就只好發這個默認的TAG類型的
二:NFC相關androidManifest文件設置
首先是權限:<uses-permission android:name="android.permission.NFC" />
然后是sdk級別限制:建議API10開始比較合適:<uses-sdk android:minSdkVersion="10"/>
接著是特殊功能限制<uses-feature android:name="android.hardware.nfc" android:required="true" />
聲明使用者必須擁有nfc功能。
三:NFC標簽過濾
在activity的intent過濾xml聲明中,你可以同時聲明過濾這三種action.但是由之前所說,你應該知道系統在發送intent的時候是有優先級的,所以你最好清楚自己最想處理哪個。
1:過濾ACTION_TAG_DISCOVERED:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
這個最簡單,也是最后一個被嘗試接受intent的選項。
2:過濾ACTION_NDEF_DISCOVERED:
<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的mimeType類型了,這個定義的越準確,intent指向你這個activity的成功率就越高,否則系統可能不會發出你想要的NDEF intent了。下面在講如何使用NDEF寫入NFC標簽的時候會多舉幾個類型的例子。
3:過濾ACTION_TECH_DISCOVERED:
你首先需要在你的<project-path>/res/xml下面創建一個過濾規則文件。名字任取,比如可以叫做nfc_tech_filter.xml。這個里面定義的是nfc實現的各種標準,每一個nfc卡都會符合多個不同的標準,個人理解為這些標準有些相互之間也是兼容的。你可以在檢測到nfc標簽后使用getTechList()方法來查看你所檢測的tag到底支持哪些nfc標準。
一個nfc_tech_filter.xml中可以定義多個<tech-list>結構組。每一組代表我聲明我只接受同時滿足這些標準的nfc標簽。比如A組表示,只有同時滿足IsoDep,NfcA,NfcB,NfcF這四個標準的nfc標簽的intent才能進入。A與B組之間的關系就是只要滿足其中一個就可以了。換句話說,你的nfc標簽技術,滿足A的聲明也可以,滿足B的聲明也可以。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list> --------------------------------A組
<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-list>
<tech-list>-----------------------------------------B組
<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>
在androidManifest文件中聲明xml過濾的舉例如下
<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>
4:nfc標簽前臺分發系統
之所以把他也歸類在nfc的過濾里面,主要是因為他跟解析nfc標簽到不是那么的緊密,他解決的是接受哪些nfc標準的標簽問題。所以更接近nfc的過濾。
什么叫nfc的前臺發布系統?就是說當我們已經打開我們的應用的時候,那么通過這個前臺發布系統的設置,我們可以讓我們已經啟動的activity擁有更高的優先級來依據我們在代碼中定義的標準來過濾和處理intent,而不是讓別的聲明了intent filter的activity來干擾,甚至連自己聲明在androidManifest中的intent filter都不會來干擾。也就是說foreground Dispatch的優先級大于intent filter。
第一種情況:當你的activity沒有啟動的時候,去掃描tag,那么系統中所有的intent filter都將一起參與過濾。
第二種情況:當你的actiity啟動了,去掃描tag時,那么將直接使用你在foreground dispatch中代碼寫入的過濾標準。如果這個標準沒有命中任何intent,那么系統將使用所有activity聲明的intent filter xml來過濾。
在OnCreate中你可以添加如下代碼
mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// 做一個IntentFilter過濾你想要的action 這里過濾的是ndef
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
//如果你對action的定義有更高的要求,比如data的要求,你可以使用如下的代碼來定義intentFilter
// try {
// ndef.addDataType("/");
// } catch (MalformedMimeTypeException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//生成intentFilter
mFilters = new IntentFilter[] {
ndef,
};
// 做一個tech-list。可以看到是二維數據,每一個一維數組之間的關系是或,但是一個一維數組之內的各個項就是與的關系了
mTechLists = new String[][] {
new String[] { NfcF.class.getName()},
new String[]{NfcA.class.getName()},
new String[]{NfcB.class.getName()},
new String[]{NfcV.class.getName()}
};
在onPause和 onResume中需要加入相應的代碼。
public void onPause() {
super.onPause();
//反注冊 mAdapter.disableForegroundDispatch(this);
}
public void onResume() {
super.onResume();
//設定intentfilter和tech-list。如果兩個都為null就代表優先接收任何形式的TAG action。也就是說系統會主動發TAG intent。
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}