2014年8月18日 星期一

NFC Basics

  - NDEF的data有兩個主要用途:
    1. 從NFC tag讀取NDEF data
    2. 利用Android Beam將NDEF messages從一台機器傳送到另一台機器

The Tag Dispatch System
  - 當Android機台發現一個NFC tag時,最好是可以直接叫起最適當的activity來處理它而不用讓使用者選擇哪個application來處理,因為選擇的動作可能會讓使用者必須將機台離開tag。

  - Android提供一個特別的tag dispatch system
    1. Parse這個tag,找出data的MIME type或URI
    2. 封裝這個MIME type或URI到一個intent裡面
    3. 根據這個intent啟動activity


NFC tags如何map到MIME types跟URIs
  - NDEF data
    - 被封裝在一個message (NdefMessage)內
    - 包含一個或多個record (NdefRecord)
  - Android也能支援沒有NDEF data的tags,透過android.nfc.tech package來處理

  - 在標準的NDEF message中,第一個NdefRecord包含下列欄位:
     1. 3-bit TNF (Type Name Format)
        決定如何解譯variable length type欄位,如下表
Type Name Format (TNF)Mapping
TNF_ABSOLUTE_URIURI based on the type field.
TNF_EMPTYFalls back to ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPEURI based on the URN in the type field. The URN is encoded into the NDEF type field in a shortened form: <domain_name>:<service_name>. Android maps this to a URI in the form: vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIAMIME type based on the type field.
TNF_UNCHANGEDInvalid in the first record, so falls back to ACTION_TECH_DISCOVERED.
TNF_UNKNOWNFalls back to ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWNMIME type or URI depending on the Record Type Definition (RTD), which you set in the type field. See Table 2. for more information on available RTDs and their mappings.
     2. Variable Length Type
         - 描述這個record的type
         - 若在上個欄位使用TNF_WELL_KNOWN,則此欄位用來描述Record Type Definition (RTD),如下表所示:
Record Type Definition (RTD)Mapping
RTD_ALTERNATIVE_CARRIERFalls back to ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIERFalls back to ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUESTFalls back to ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECTFalls back to ACTION_TECH_DISCOVERED.
RTD_SMART_POSTERURI based on parsing the payload.
RTD_TEXTMIME type of text/plain.
RTD_URIURI based on payload.
     3. Variable Length ID
        - 這個record的unique ID
        - 這個欄位並不常用,只有當想標明唯一tag時才需要產生這個ID

     4. Variable Length Payload
        - 想要讀/寫的實際data payload
        - 由於一個NDEF message可能有好幾個record,所以第一個record並不一定包含全部的payload

  - 若可mapping成功,則tag dispatch system會把這個map的資訊以及實際的payload封裝到一個ACTION_NDEF_DISCOVERED intent
  - 若無法辨別,則會將一 Tag 物件(包含tag的技術以及payload等資訊)封裝到一個ACTION_TECH_DISCOVERED intent

  - 舉例來說,當tag dispatch system遇到TNF_ABSOLUTE_URI,則它會將variable length type欄位map到一個URI,接著把這個UIR封裝到ACTION_NDEF_DISCOVERED intent中,同時也會把其他的資訊(如payload)一起包進去。


NFC tags如何dispatch到application
  - tag dispatch system定義了三個intent,優先權由高到低如下:
     1. ACTION_NDEF_DISCOVERED
     2. ACTION_TECH_DISCOVERED
     3. ACTION_TAG_DISCOVERED




Requesting NFC Access in the Android Manifest
  - 必須使用<uses-permission> element以存取NFC hardware
<uses-permission android:name="android.permission.NFC" />

  - 使用<uses-feature> element則有NFC的device才能在Google Play上看到你的AP
<uses-feature android:name="android.hardware.nfc" android:required="true" />

  - 如果不想用<uses-feature>,那就用NfcAdapter.getDefaultAdapter()動態檢查NFC是否存在



Filtering for NFC Intents
ACTION_NDEF_DISCOVERED
  - 例子: 用intent filter指出你想處理MIME type為text/plain的intent

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
</intent-filter>

  - 例子:處理 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
  - 必須建立一個xml resource檔指出你的activity支持那些技術
<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>