文章來源:NFC Basics,此文章是google 官方對NFC的簡介。
本文檔介紹了基本的NFC任務在Android上。它說明了如何發送和接收的NDEF消息的形式數據,並介紹支持這些功能的框架API。對於更高級內容,包括非NDEF數據的討論,請參閱高級NFC。
在Android使用NDEF數據,有兩個主要的用途:
● 閱讀NDEF數據從一個NFC標籤
● 傳送NDEF信息從一個設備到另一個支持Android Beam的設備
標籤的調度系統處理從一個NFC標籤讀取NDEF數據,它分析發現的NFC標籤,適當的數據進行分類,並針對不同的數據啓動一個應用程序。要處理的掃描NFC標籤的應用程序可以聲明一個意圖過濾器,並要求處理的數據。
Android Beam功能,允許一臺設備推送NDEF消息另一臺設備上通過兩臺設備物理接觸在一起。這種相互作用提供了一個比其它無線技術簡單的方法來發送數據,如藍牙,因爲有了NFC,手動發現設備或配對不是必需的。兩個設備進入範圍時,連接自動啓動。Android Beam 也成爲了一種可能可通過NFC 的一系列API,因此,任何應用都可以在設備之間傳輸信息。例如:聯繫人,瀏覽器和YouTube應用程序使用Android Beam與其他設備共享聯繫人,網頁和視頻。
標籤調度系統
Android設備通常是在屏幕解鎖的時候掃描NFC標籤,除非NFC功能在設置菜單中被禁用。當Android 設備發現了一個NFC標籤,啓動最適當的activity處理intent,而不需要詢問用戶使用什麼應用程序處理。因爲設備掃描NFC標籤在很短的範圍內,讓用戶手動選擇的活動很有可能將迫使他們從標籤上移動設備,進而斷開連接。應該開發activity處理NFC標籤,activity以防止activity選擇出現。
爲實現這個目標,Android提供了一個特殊的標籤調度系統來分析掃描NFC標籤並解析它們,並試圖在掃描數據中找到對應的的應用程序。這是通過:
1. 解析NFC標籤和搞清楚的MIME類型或在標籤中用於標識一個數據URI。
2. 封裝MIME類型或URI和有效載荷到Intent。前兩個步驟在下面的”NFC標籤是如何映射到MIME類型和URI“中有介紹。
3. 基於Intent啓動activity。這部分具體描述在” 如何NFC標籤被分派到應用“。
NFC標籤是如何映射到MIME類型和URI
在開始寫NFC應用前,重要的是要了解不同類型的NFC標籤,調度系統如何解析NFC標籤,和當標籤調度系統檢測到一個NDEF消息時的專項的工作。NFC標籤來在各種各樣的技術組織,也可以有許多不同方式的數據寫入。Android使用的是最受支持的NDEF標準,它是由NFC論壇定義的。NDEF數據被封裝內部消息(NdefMessage),它包含一個或多個的記錄(NdefRecord)。每個NDEF記錄必須形成規範的記錄。Android還支持其他的標籤不包含NDEF數據,可以通過使用在android.nfc.tech包中的類。要了解有關這些技術的更多信息,請參閱高級NFC篇。工作涉及到編寫自己的協議棧與其他類型的標籤進行通信,因此我們建議在可能的情況下使用NDEF爲易於開發和對Android的設備的最大支持。
★注意: 要下載完整的的NDEF規範,請到NFC論壇,參考創建通用NDEF記錄 ,學習如何構建NDEF記錄。
現在有了NFC標籤的一些背景知識,下面的章節更詳細的描述了Android是如何處理NDEF格式的標籤。當Android手機掃 描一個包含NDEF數據格式的NFC標籤,它會解析消息,並試圖找出數據的MIME類型或標識URI。要做到這一點,系統讀取NdefMessage裏的第一個NdefRecord,以確定如何解析整個的的NDEF消息(NDEF消息可以有多個NDEF記錄)。在一個良好的NDEF消息,第一NdefRecord 包含以下字段:
3-bit TNF (Type Name Format)
指示如何解析variable length type區域。有效值像在表1中描述的。
Variable length type
描述記錄類型。如果使用TNF_WELL_KNOWN,使用此字段指定記錄類型定義(RTD)。有效的RTD值描述在表2中。
Variable length ID
記錄的唯一標識符。此字段不經常使用,但如果需要唯一識別的標籤,你可以爲其創建一個ID。
Variable length payload
這個是要讀取或寫入的實際數據負載。NDEF消息可以包含多個NDEF記錄,所以不要以爲全部負載就是在第一NDEF創紀錄的NDEF消息。
標籤調度系統使用TNF和類型字段試圖去映射的MIME類型或URI的NDEF消息。如果成功的話,它封裝了內部信息的實際有效載荷的ACTION_NDEF_DISCOVERED intent。然而,也會發生標籤調度系統不能基於第一NDEF記錄的數據確定類型。發生這種情況時,NDEF數據不能被映射到一個MIME類型或URI,或當NFC標籤不包含NDEF數據做爲開始。在這種情況下,標籤的對象,該對象具有標記的技術和有效載荷的信息,封裝一個成ACTION_TECH_DISCOVERED intent。
表1。介紹了標籤調度系統如何根據TNF和類型字段映射到MIME類型或URIs。也說明了哪些TNFs不能被映射到MIME類型或URI。在這種情況下,標籤調度系統回到 ACTION_TECH_DISCOVERED的。
例如,如果標籤調度系統遇到一個類型TNF_ABSOLUTE_URI紀錄,該記錄的可變長度類型字段映射到一個URI。標籤調度系統將該URI封裝成ACTION_NDEF_DISCOVERED的Intent,並攜帶關於標籤的其他信息,如負載。另一方面,如果它遇到的的記錄類型TNF_UNKNOWN,它創建封裝標籤技術的Intnet。
類型名稱格式(TNF) | 映射 |
---|---|
TNF_ABSOLUTE_URI
|
基於URI的基礎類型字段 |
TNF_EMPTY |
回到 ACTION_TECH_DISCOVERED 。 |
TNF_EXTERNAL_TYPE |
在類型字段中基於URN的URI。URN被編碼成NDEF類型縮寫形式:<domain_name>:<service_name> 。Android映射成URI的形式: vnd.android.nfc
://ext/ <domain_name>:
<service_name> 。 |
TNF_MIME_MEDIA |
基於類型字段MIME字段。 |
TNF_UNCHANGED |
無效的第一條記錄中,因此回落到 ACTION_TECH_DISCOVERED的 。 |
TNF_UNKNOWN |
回到 ACTION_TECH_DISCOVERED 。 |
TNF_WELL_KNOWN |
根據記錄類型定義(RTD),在類型字段設置MIME類型或URI。RTD和映射的更多信息,請參閱表2。 |
記錄類型定義(RTD) | 映射 |
---|---|
RTD_ALTERNATIVE_CARRIER |
回到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_CARRIER |
回到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_REQUEST |
回到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_SELECT |
回到 ACTION_TECH_DISCOVERED 。 |
RTD_SMART_POSTER |
基於解析有效載荷的URI。 |
RTD_TEXT |
MIME類型爲text / plain 。 |
RTD_URI |
基於有效載荷URI。 |
NFC標籤分發到應用
標籤調度系統創建一個intent,intent封裝了NFC標籤和它的識別信息,調度系統發送給對應的應用程序,它是依據intent的過濾器。如果有一個以上的應用程序可以處理這個intent,activity選擇器就會出現,使用戶可以選擇的activity。標籤調度系統定義了三個意向,按照最高優先級到最低優先級的順序:
1. ACTION_NDEF_DISCOVERED:當包含NDEF有效載荷或是一個公認的類型的NFC tag被掃描到時,這個Intent用來啓動一個activity。這是最高優先級的intent,標籤調度系統嘗試用這個intent啓動一個activity,早於任何其他的intent。
2. ACTION_TECH_DISCOVERED:如果沒有activity處理ACTION_NDEF_DISCOVERED intent,標籤調度系統嘗試使用這個intent啓動應用程序。如果被掃描tag包含NDEF的數據不能被映射到一個MIME類型或URI,或者tag不包含NDEF數據,但是是一個已知的標籤技術,在這兩種情況下,此intent也可以直接啓動(首先沒有啓動ACTION_NDEF_DISCOVERED)。
3. ACTION_TAG_DISCOVERED:在沒有activity處理ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED的 intent時,此intent纔會被啓用。
標籤調度系統的工作原理,基本方法如下:
1. 用intent啓動一個activity,此intent是由標籤調度系統解析NFC的tag所創建的(ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED)。
2. 如果activity過濾器沒有過濾那個intent,就要用下一個低優先級的的intent(ACTION_TECH_DISCOVERED或ACTION_TAG_DISCOVERED)啓動activity,直到應用程序過濾器找到相應的intent,或者標籤調度系統嘗試所有可能的intent。
3. 如果應用程序不針對任何的intent過濾,那就do nothing。
只要有可能,都會用NDEF 消息和ACTION_NDEF_DISCOVERED 來工作,因爲它是三個Intent中最突出使用的。ACTION_NDEF_DISCOVERED 可以比其他的兩個intent能在更合適的時間啓動應用,給了用戶很好的體驗。
AndroidManifest NFC訪問的請求
在訪問NFC硬件設備和妥善處理NFCintent之前,需要在AndroidManifest.xml文件做如下動作
●訪問NFC硬件的權限:
<uses-permission android:name="android.permission.NFC" />
●應用支持的最小SDK的版本。API 9通過ACTION_TAG_DISCOVERED只支持有限的標籤派遣,只通過額外 的EXTRA_NDEF_MESSAGES訪問NDEF消息。沒有其他標記的屬性或I / O操作都可以訪問。API 10包括對NDEF有了全面的讀/寫支持,API 14提供了一個簡單的方法來推送NDEF消息到其他設備和額外便捷的方法創建NDEF記錄。
<uses-sdk android:minSdkVersion="10"/>
●uses-feature可以使應用在google Play僅向支持NFC的功能的設備顯示
<uses-feature android:name="android.hardware.nfc" android:required="true" />
如果應用程序使用NFC功能,但該功能並不重要對於應用程序來說,那就可以省略uses-feature元素,並在運行時檢查NFC的可用性,看看getDefaultAdapter() 是否爲null。
NFC Intent 過濾
爲了要處理掃描的NFC標籤而啓動應用程序,應用程可以過濾一個,兩個或全部三個NFC intent,在Android manifest 中配置。然而,通常希望控制應用程序啓動時過濾ACTION_NDEF_DISCOVERED。沒有應用處理ACTION_NDEF_DISCOVERED或者負載數據不是NDEF時,ACTION_TECH_DISCOVERED是一個ACTION_NDEF_DISCOVERED的備用。通常ACTION_TAG_DISCOVERED是過於籠統的類別過濾。許多應用程序將過濾ACTION_TAG_DISCOVERED之前過濾ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED,所以應用程序啓動的概率很低。ACTION_TAG_DISCOVERED僅可作爲應用處理的最後手段,防止沒有其他應用程序處理
ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED。
由於NFC標籤部署有所不同,很多時候不是你的控制之下,這並不總是可能的,這就是爲什麼在必要時可以回退到其他兩個意圖。當你有類型的標籤和數據寫入的控制權,它是建議使用的NDEF格式化標籤。以下各節描述了每種intent如何過濾。
ACTION_NDEF_DISCOVERED
爲了過濾ACTION_NDEF_DISCOVERED,聲明intent過濾器要過濾的數據類型。下面的例子是過濾器 過濾MIME類型text / plain的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>
下面的示例過濾器中的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>
ACTION_TECH_DISCOVERED
如果activityx想過濾ACTION_TECH_DISCOVERED,你必須創建含有activity支持tag的tech-list列表XML資源文件。如果tech-list列表的一個子集的技術可以被tag所支持的話,則activity被認爲是匹配的,你可以得到通過調用getTechList()獲取到tech-list列表 。例如,如果掃描到的tag支持MifareClassic的,NdefFormatable,NfcA,tech-list列表必須指定所有三個,兩個或技術中的一個(還可以有其他的),以便匹配activity。下面的示例定義的所有技術。你可以刪除你不需要的那些。將此文件保存在<project-root> / res / xml文件夾(你可以將其命名爲任何你希望的) 。
<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>
還可以定義多重的tech-list列表,他們被認爲是獨立的。如果任何單一的tech-list列表中技術作爲getTechList()返回集合的子集,那activity被認爲是匹配的。這提供了AND和OR 匹配技術。下面的例子匹配的標籤,可以支持NFCA及NDEF,也可以支持NfcB 和NDEF:<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>
</resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
在AndroidManifest.xml文件中,指定剛剛創建資源文件到的<meta-data>元素,它是<activity> 元素的子元素,下面的例子:<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>
關於tag技術和ACTION_TECH_DISCOVERED協作更多信息,請參閱高級NFC文檔。
ACTION_TAG_DISCOVERED
要過濾ACTION_TAG_DISCOVERED使用下面的intent過濾器:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
從意圖獲取信息
如果一項活動開始因爲NFC的intent,從intent可以得到掃描到的NFC標籤的信息。intent包含依附在tag上以下額外的信息:
● EXTRA_TAG(必需的):標籤對象代表掃描標籤。
● EXTRA_NDEF_MESSAGES(可選):解析tag獲取的NDEF消息數組。這額外的意圖是強制性的。
● {android.nfc.NfcAdapter#EXTRA_ID(可選):低級別的ID標籤。
要獲得這些額外檢查,看是否活動推出的與NFC意圖之一,以確保標籤被掃描,然後獲取額外的意圖。下面的例子檢查的ACTION_NDEF_DISCOVERED 意圖,並得到意向額外的NDEF消息。
未完待續