序文:
這份文件描述了比較進階部分的NFC主題,像是處理不同種類的tag technologies,
寫入NFC tags,以及前景的調度(dispatching),它允許一個app在前景可以處理intents,
即便其他app篩相同的東西。
Working with Supported Tag Technologies:
當用NFC tags及Android的裝置時,主要使用的讀寫格式是NDEF。
當一個裝置掃一個含NDEF data的tag,Android提供對於message的parsing支援,
並如果可以的話遞交一個
NdefMessage
。有些狀況是當你掃一個不含NDEF資料的tag的時候,
你需要直接和tag開啟溝通並自己寫自己的protocol(in raw bytes)。
Android對此狀況提供了一般的支援在
android.nfc.tech
package裡,定義在下面的第一張表。你可以使用
getTechList()
method,來決定被支援的technologies,且製作對應的TagTechnology物件,
使用
android.nfc.tech
提供的classes。Class | Description |
---|---|
TagTechnology | The interface that all tag technology classes must implement. |
NfcA | Provides access to NFC-A (ISO 14443-3A) properties and I/O operations. |
NfcB | Provides access to NFC-B (ISO 14443-3B) properties and I/O operations. |
NfcF | Provides access to NFC-F (JIS 6319-4) properties and I/O operations. |
NfcV | Provides access to NFC-V (ISO 15693) properties and I/O operations. |
IsoDep | Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations. |
Ndef | Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF. |
NdefFormatable | Provides a format operations for tags that may be NDEF formattable. |
下面的tag technologies並不被要求在Android裝置上支援。
Class | Description |
---|---|
MifareClassic | Provides access to MIFARE Classic properties and I/O operations, if this Android device supports MIFARE. |
MifareUltralight | Provides access to MIFARE Ultralight properties and I/O operations, if this Android device supports MIFARE. |
Working with tag technologies and the ACTION_TECH_DISCOVERED intent:
當一個裝置掃描一個上面帶有NDEF資料的tag,但沒辦法對應到MIME或URI,
tag dispatch系統會嘗試去以
ACTION_TECH_DISCOVERED
intent來開它。(上一篇有提過) ACTION_TECH_DISCOVERED
也會被使用,當一個非NDEF資料的tag被掃描時。因為有這個fallback,允許你直接在tag上的資料作處理。
(如果tag dispatch系統沒辦法幫你parse的話)
基本的步驟如下:
1. 去篩ACTION_TECH_DISCOVERED的intent,條件設為篩你想處理的那些tag technologies。
會做什麼事情前面那篇也都講了。
2. 當你的app收到intent時,從intent裡抓取Tag物件:
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
3. 藉由呼叫android.nfc.tech package裡的
get
factory methods,取得
TagTechnology
的實例(instance)。你可以枚舉(enumerate)支援的technologies of the tags,藉由在呼叫
get
factory method之前先呼叫getTechList()。舉例來說你想從
Tag
獲得一個MifareUltralight
的實例,照下面這樣作:MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Reading and writing to tags:
讀寫一個NFC tag的過程,跟從intent獲得tag以及開啟和tag溝通有關。
你必須定義你自己的protocol stack來讀寫資料到tag。
記得,不論如何,當你要直接處理tag時,你仍然是要讀寫NDEF資料。
是否要不要作架構的決定權在你。
下面的例子展示了如何去處理一個MIFARE Ultralight tag。
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
Using the Foreground Dispatch System:
前景調度系統允許一個activity去截下一個intent,
並且聲稱比其他的activities有更高的優先權來處理同一個intent。
使用這個系統,要引入建構一些資料結構給Android系統能夠傳送適當的intents到你的app。
要打開這個系統:
1. 加入下面的code到
onCreate()
activity的method裡:a. 作一個PendingIntent物件讓Android系統可以將詳細的tag資訊在被掃的時候能將其填進去
PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);b. 聲明intent filters來處理你想攔下的intents。
前景調度系統在裝置掃到tag並傳出intent時會檢查指定的的intent filters。
如果相符那麼你的app會處理intent。若否,前景調度系統會falls back到intent dispatch system。
指定一個null的intent filters和technology filters的陣列,
指定你要篩所有fallback到TAG_DISCOVERED intent的tags。
下面的程式碼片段處理所有NDEF_DISCOVERED的MIME types。
你應該只去處理你需要的部分。
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, };
c. 設定好你的app想要處理的一個tag technologies的陣列。
呼叫Object.class.getName() method來獲取你要支援的technology的class。
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
2. 複寫下面的activity生命週期的callbacks,並加上邏輯去控制前景調度的開關。
(當activity失去(
onPause()
) 和重新獲得 (onResume()
) 焦點(focus))enableForegroundDispatch()必須被從main thread來呼叫,
且只有當activity是在前景時這麼做。(呼叫onResume()可以保證這點)。
你也需要去實作
onNewIntent
callback來從被掃的NFC tag來處理資料。public void onPause() { super.onPause(); mAdapter.disableForegroundDispatch(this); } public void onResume() { super.onResume(); mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); } public void onNewIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); //do something with tagFromIntent
可以參考API Demo的 ForegroundDispatch sample來看完整的範例。
沒有留言:
張貼留言