Part16 開發NFC程式 單元80 NFC程式設計 單元81 把資料寫入NFC tag 單元82 NFC的進階用法 2
單元80 NFC程式設計
NFC (Near Field Communication) NFC 是一種新興的手機應用,運作方式是讓手機靠近一個含有NFC tag的裝置或是小貼片,以取得或傳送資料如圖80-1,它可以用在手機付款、個人資料交換、商品資料擷取…等。
NFC (Near Field Communication) 最基本的用法是所謂的NFC Data Exchange Format簡稱NDEF,它具有下列二種功能: 1. 從NFC tag讀取NDEF資料。 2. 從一個NFC裝置傳送NDEF資料到另一個NFC裝置。 當Android系統偵測到NFC tag時,它會利用Tag Dispatch機制來進行處理,Tag Dispatch的過程牽涉到NFC tag資料的解析和建立Intent物件 5
Android處理NFC tag資料的方式 在NFC tag中NDEF資料是封裝在一個NFC message裡面,NFC message內部可以有一個或多個record,第一個record含有以下資訊: 1.TNF (Type Name Format) 決定Type欄位的格式,TNF可以是下一頁的幾種設定值。 2.Type TNF欄位的值決定此欄位的資料格式,例如如果TNF的值是TNF_WELL_KNOWN,這個欄位就是RTD (Record Type Definition)。 3.ID record的ID編號,通常不需要設定。 4.Payload 用來儲存實際的資料,NFC message中的資料可以分開儲存在多個record中。 6
Android處理NFC tag資料的方式 TNF的設定值 說明 TNF_ABSOLUTE_URI Type欄位是URI資料 TNF_EMPTY Android系統會以 ACTION_TECH_DISCOVERED的方式處理 TNF_EXTERNAL_TYPE Type欄位是URN 型態的URI,Android會將它的格式轉成vnd.android.nfc://ext/<domain_name>:<service_name> TNF_MIME_MEDIA Type欄位是描述MIME的型態 TNF_UNCHANGED TNF_UNKNOWN TNF_WELL_KNOWN Type欄位是RTD 7
Android處理NFC tag資料的方式 Type欄位的值(RTD) 說明 RTD_ALTERNATIVE_CARRIER Android系統會以 ACTION_TECH_DISCOVERED的方式處理 RTD_HANDOVER_CARRIER RTD_HANDOVER_REQUEST RTD_HANDOVER_SELECT RTD_SMART_POSTER Payload欄位是URI RTD_TEXT MIME型態是text/plain. RTD_URI 8
Android處理NFC tag資料的方式 當Android手機或平板電腦的螢幕被解鎖之後,Android系統便開始連續不斷地偵測NFC tag(使用者可以利用手機或平板電腦的系統設定取消這項功能)。 當偵測到NFC tag時,Android系統開始分析從NFC tag中取得的資料。首先利用TNF和Type二個欄位決定資料是否屬於MIME或是URI型態。如果是的話代表這個NFC tag是屬於NDEF,接著取出實際的資料,再將它包裝成一個ACTION_NDEF_DISCOVERED型態的Intent物件,然後搜尋目前安裝的程式,找出誰能夠處理這個Intent物件,然後啟動該程式把Intent物件交給它處理。 如果Android系統分析NFC tag的結果發現不是NDEF,便會建立一個ACTION_TECH_DISCOVERED型態的Intent物件,其中包含一個Tag物件和從NFC tag中取出的資料。 9
Android處理NFC tag資料的方式 例如NFC message中的第一個record的TNF是TNF_ABSOLUTE_URI,則表示Type欄位就是URI,此時Android會取出該URI連同Payload中的資料一起包裝成一個ACTION_NDEF_DISCOVERED型態的Intent物件。 如果NFC message的第一個record的TNF是TNF_UNKNOWN,則Android會建立一個ACTION_TECH_DISCOVERED型態的Intent物件。 當Android根據NFC tag中的資料建立好Intent物件後,便開始搜尋可以處理該Intent的程式,並根據下列步驟進行後續操作。 10
Android處理NFC tag資料的方式 步驟一: 如果是ACTION_NDEF_DISCOVERED型態的Intent而且有程式可以進行處理,就啟動該程式,然後把Intent傳給它,如果找不到可以處理的程式就進行下一個步驟。 步驟二: 重新建立一個ACTION_TECH_DISCOVERED型態的Intent,然後尋找可以處理它的程式。如果有找到就啟動該程式然後把Intent傳給它,如果找不到可以處理的程式就進行下一個步驟。 步驟三: 重新建立一個ACTION_TAG_DISCOVERED型態的Intent,然後尋找可以處理它的程式。如果有找到就啟動該程式然後把Intent傳給它,如果找不到可以處理的程式就放棄處理這個NFC tag的資料。 11
Android處理NFC tag資料的方式 12
開發NFC程式 要讓程式能夠處理NFC tag的資料必須先在程式功能描述檔AndroidManifest.xml中完成以下設定: <?xml version="1.0" encoding="utf-8"?> <manifest ...> ... <uses-sdk android:minSdkVersion="10" /> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application ...> … </application> </manifest> 13
開發NFC程式 接下來是設定程式能夠處理的NFC Intent的形式,這其實是利用單元四十介紹的Intent Filter技術。例如要讓程式能夠處理ACTION_NDEF_DISCOVERED型態的Intent,而且資料是屬於MIME的text形式,就必須在程式功能描述檔中加入以下設定: <?xml version="1.0" encoding="utf-8"?> <manifest …> … <application …> <activity …> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter> </activity> </application> </manifest> 14
開發NFC程式 如果程式要處理的資料是屬於URI型態,而且內容是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> 15
開發NFC程式 如果要讓程式能夠處理ACTION_TECH_DISCOVERED型態的Intent,必須先在程式專案的res資料夾中新增一個xml子資料夾,並且在裡頭建立一個xml檔,例如可以將它取名為nfc_tech_list.xml,然後編輯它的內容如下: <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> <tech>android.nfc.tech.NfcB</tech> </resources> 這個檔案定義程式能夠處理的NFC tag形式,以這個範例而言表示程式能夠處理NfcA搭配Ndef的形式,或者是NfcB搭配Ndef的形式。 16
開發NFC程式 然後在程式功能描述檔中加入下列設定: <?xml version="1.0" encoding="utf-8"?> <manifest …> … <application …> <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_list" /> </activity> </application> </manifest> 17
開發NFC程式 程式收到NFC Intent之後必須從中取出資料,一般來說資料會以下列二種方式儲存在Intent中: 1. EXTRA_TAG 表示是一個Tag型態的物件。 2. EXTRA_NDEF_MESSAGES 表示這是NDEF型態的資料。 18
開發NFC程式 以下程式碼範例先檢查接收到的NFC Intent是否為ACTION_NDEF_DISCOVERED型態,如果是的話再從中取出EXTRA_NDEF_MESSAGES形式的資料: public void onResume() { super.onResume(); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMsgs != null) { msgs = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { msgs[i] = (NdefMessage) rawMsgs[i]; } //處理msgs[]陣列中的資料 … 19