本文基本是結合Android Developer
官網進行梳理,NFC
系列將由基本概念到具體操做,到NDEF
和非NDEF
的數據讀寫。html
參考資料android
NFC概覽編程
近距離無線通訊 (NFC :``Near Field Communication``)
是一組近距離無線技術,一般只有在距離不超過 4
釐米時才能啓動鏈接。藉助 NFC
,您能夠在 NFC
標籤與 Android
設備之間或者兩臺 Android
設備之間共享小型負載。瀏覽器
標籤的複雜度可能各有不一樣markdown
簡單標籤僅提供讀取和寫入語義,有時可以使用一次性可編程區域將卡片設置爲只讀網絡
較複雜的標籤可提供數學運算,還可以使用加密硬件來驗證對扇區的訪問權限app
最爲複雜的標籤可包含操做環境,容許與針對標籤執行的代碼進行復雜的互動框架
存儲在標籤中的數據也能夠採用多種格式編寫,但許多 Android
框架 API
都基於名爲 NDEF
(NFC
數據交換格式)的 NFC Forum 標準。ide
支持 NFC
的 Android
設備同時支持如下三種主要操做模式:oop
讀取器/寫入器模式:支持 NFC
設備讀取和/或寫入被動 NFC
標籤和貼紙。
點對點模式:支持 NFC
設備與其餘 NFC
對等設備交換數據;Android Beam
使用的就是此操做模式。
卡模擬模式:支持 NFC
設備自己充當 NFC
卡。而後,能夠經過外部 NFC
讀取器(例如 NFC
銷售終端)訪問模擬 NFC
卡。
主要有兩種 ---- 無源NFC設備與有源NFC設備
無源NFC
設備包括NFC
標籤和其餘小型發射器,它們能夠向其餘NFC
設備發送信息,而不須要電源。可是,它們不能處理來自其餘源的信息,也不能鏈接到其餘無源設備。
有源NFC
設備可以發送和接收數據,而且能夠彼此通訊,也能夠與無源設備通訊。目前來講,智能手機是最多見的有源NFC
設備,其它常見的例子還包括公交讀卡器和支付終端。
若是從工做模式上來介紹的話,能夠這樣歸納
NFC
工做模式分爲被動模式和主動模式。
被動模式中NFC
發起設備(也稱爲主設備)須要供電設備,主設備利用供電設備的能量來提供射頻場,並將數據發送到NFC目標設備(也稱做從設備),傳輸速率需在106kbps
、212kbps
或424kbps
中選擇其中一種。從設備不產生射頻場,因此能夠不須要供電設備,而是利用主設備產生的射頻場轉換爲電能,爲從設備的電路供電,接收主設備發送的數據,而且利用負載調製(load modulation
)技術,以相同的速度將從設備數據傳回主設備。由於此工做模式下從設備不產生射頻場,而是被動接收主設備產生的射頻場,因此被稱做被動模式,在此模式下,NFC
主設備能夠檢測非接觸式卡或NFC
目標設備,與之創建鏈接。
主動模式中,發起設備和目標設備在向對方發送數據時,都必須主動產生射頻場,因此稱爲主動模式,它們都須要供電設備來提供產生射頻場的能量。這種通訊模式是對等網絡通訊的標準模式,能夠得到很是快速的鏈接速率。
它的工做原理是什麼呢?就像藍牙、Wi-Fi
以及其餘各類無線通訊技術同樣,NFC
的工做原理也是經過無線電波發送信息,也是無線數據傳輸的一種標準。這意味着設備必須遵照特定的規範,才能正確地相互通訊。在NFC中使用的技術是基於舊的免接觸式射頻識別(RFID
)演變而來,即使用電磁感應來傳輸信息,並向下兼容RFID
。
這也是NFC
和藍牙/WiFi的一個主要區別,NFC
使用電磁感應原理,有源NFC元件能夠在無源元件中感應出電流和發送數據。這意味着無源設備不須要本身的電源,當NFC組件進入通訊範圍時,它們能夠由有源NFC
組件產生的電磁場提供動力。不過,NFC
技術沒有足夠的感應力來給咱們的智能手機充電,QI
無線充電也是基於一樣的原理。
NFC
的工做頻率爲13.56MHz,距離在10釐米內,其傳輸速度有106Kbit/秒、212Kbit/秒或者424Kbit/秒三種,這種傳輸速度對於傳輸圖片和音樂等文件已經足夠了。
NFC
的優點
NFC
相比藍牙的一大優點是功耗更少,這使得NFC
很是適合於做爲無源設備,好比前面提到的廣告標籤,由於它們能夠在沒有電源的狀況下運行。
還有一個主要優點:鏈接速度更快。NFC
因爲使用了電感耦合技術,無需手動配對,在兩個設備之間創建鏈接僅需不到十分之一秒的時間。雖然現代藍牙鏈接速度已經很是快了,但依然遠不及NFC
的鏈接速度,而快速的鏈接對於某些場景是相當重要的,例如移動支付。
固然,缺點也有
NFC
的傳輸距離比藍牙短得多。上面說過,NFC
的最大傳輸範圍約爲10釐米,而藍牙鏈接的傳輸距離能夠高達10米甚至更遠。NFC
的另外一個缺點是其傳輸速度比藍牙慢不少。NFC
傳輸數據的最高速度僅爲424 kbit/s,而藍牙2.1的傳輸速度爲2.1 Mbit/s,**藍牙LE(低功耗)**的傳輸速度也達到了爲1 Mbit/s。將 NDEF
數據與 Android
結合使用時,會有兩個主要用例
從 NFC
標籤讀取 NDEF
數據
NFC
標籤讀取 NDEF
數據的操做由標籤調度系統進行處理,該系統會分析已發現的 NFC
標籤,對相應數據進行適當分類,而後啓動對分類後的數據感興趣的應用。若是某個應用想要處理掃描到的 NFC
標籤,則能夠聲明 Intent 過濾器,並請求對數據進行處理使用 Android Beam™ 將 NDEF
消息從一臺設備傳輸到另外一臺設備
Android Beam™
功能,設備能夠將 NDEF
消息推送到另外一臺設備,方法是將兩臺設備靠在一塊兒。與藍牙等其餘無線技術相比,這種互動可提供更簡便的數據發送方式,由於使用 NFC
時無需手動發現設備並將其配對。當兩臺設備之間的距離近到必定範圍內時,系統會自動開始鏈接。Android Beam
功能經過一組 NFC API
提供,所以任何應用均可以在設備間傳輸信息。例如,通信錄、瀏覽器和 YouTube
應用可以使用 Android Beam
在多臺設備之間共享聯繫人信息、網頁和視頻。Android
設備一般會在屏幕解鎖後查找 NFC
標籤,除非設備的「設置」菜單中停用了 NFC
功能。
在 Android
設備發現 NFC
標籤後,指望的行爲就是讓最合適的 Activity
來處理該 Intent
,而不是詢問用戶應使用哪一個應用。
因爲設備須要在很是近的範圍內掃描 NFC 標籤,所以,讓用戶手動選擇 Activity
可能會迫使他們將設備從標籤處移開並致使鏈接中斷。應以適當方式開發 Activity
,使其僅處理所關注的 NFC
標籤,以免 Activity
選擇器出現。爲了解決這個問題,Android
提供了一個特殊的標籤調度系統,用於分析掃描到的 NFC
標籤、解析它們並嘗試找到對掃描到的數據感興趣的應用。這個標籤調度系統經過如下操做來實現這些目的:
解析 NFC
標籤並肯定 MIME
類型或 URI
(後者用於標識標籤中的數據負載)。
將 MIME
類型或 URI
與負載一塊兒封裝到 Intent
中。如何將 NFC 標籤映射到 MIME 類型和 URI 中介紹了前兩個步驟。
根據 Intent
啓動 Activity
。如何將 NFC 標籤分發到應用中介紹了此步驟。
Android
對 NFC Forum 定義的 NDEF
標準的支持最完備,NDEF
數據封裝在包含一條或多條記錄(NdefRecord
)的消息(NdefMessage
)中,也就是NdefMessage
消息中會有很多NdefRecord
記錄,咱們都是先建立NdefRecord
記錄後再放到NdefMessage
中。
注意:要下載完整的 NDEF
規範,請轉到 NFC Forum 規範和應用文檔網站,並參閱建立常見類型的 NDEF 記錄,查看有關如何構造 NDEF 記錄的示例。
當 Android
設備掃描包含 NDEF
格式數據的 NFC
標籤時,它會解析該消息並嘗試肯定數據的 MIME 類型或起標識做用的 URI
。爲此,系統須要讀取 NdefMessage
中的第一條 NdefRecord
,以肯定如何解讀整個 NDEF
消息(一個 NDEF
消息可能具備多條 NDEF
記錄)。在格式正確的 NDEF
消息中,第一條 NdefRecord
包含如下字段
3 位 TNF(類型名稱格式)
表示如何解讀可變長度類型字段。下表 中介紹了有效的值。
詳細可查看 官網表1
可變長度類型
介紹了記錄的類型。若是使用 TNF_WELL_KNOWN
,那麼請使用此字段來指定記錄類型定義 (RTD
)。下表 中介紹了有效的 RTD
值
詳細可查看 官網表2
可變長度 ID
記錄的惟一標識符。此字段並不常用,但若是您須要對標籤進行惟一標識,則可爲其建立 ID
可變長度負載
您要讀取或寫入的實際數據負載。一個 NDEF
消息能夠包含多條 NDEF
記錄,所以不要假定 NDEF
消息的第一條 NDEF 記錄中就有完整的負載
具體操做,後續會進行代碼分析,這裏能夠對照看下小米碰碰貼的NFC的NDEF記錄
具體支持可查看 官網
Android
設備還能夠選擇支持如下標籤技術
當標籤調度系統建立完用於封裝 NFC
標籤及其標識信息的 Intent
後,
它會將該 Intent
發送給感興趣的應用,由這些應用對其進行過濾。
若是有多個應用可處理該 Intent
,系統會顯示 Activity
選擇器,供用戶選擇要使用的 Activity
。
標籤調度系統定義了三種 Intent
,按優先級從高到低列出以下
ACTION_NDEF_DISCOVERED
:若是掃描到包含 NDEF
負載的標籤,而且可識別其類型,則使用此 Intent
啓動 Activity。這是優先級最高的 Intent
,標籤調度系統會盡量嘗試使用此 Intent 啓動 Activity,在行不通時纔會嘗試使用其餘 Intent
ACTION_TECH_DISCOVERED
:若是沒有登記要處理 ACTION_NDEF_DISCOVERED
Intent
的 Activity
,則標籤調度系統會嘗試使用此 Intent
來啓動應用。此外,若是掃描到的標籤包含沒法映射到 MIME
類型或 URI
的 NDEF
數據,或者該標籤不包含 NDEF
數據,但它使用了已知的標籤技術,那麼也會直接啓動此 Intent
(無需先啓動 ACTION_NDEF_DISCOVERED
)
ACTION_TAG_DISCOVERED
:若是沒有處理 ACTION_NDEF_DISCOVERED
或者 ACTION_TECH_DISCOVERED
Intent
的 Activity
,則使用此 Intent
啓動 Activity
標籤的調度系統基本工做方式以下
在解析 NFC
標籤(ACTION_NDEF_DISCOVERED
或 ACTION_TECH_DISCOVERED
)時,嘗試使用由標籤調度系統建立的 Intent
啓動 Activity
。
若是不存在過濾該 Intent
的 Activity
,則嘗試使用下一優先級的 Intent
(ACTION_TECH_DISCOVERED
或 ACTION_TAG_DISCOVERED
)啓動 Activity
,直到應用過濾該 Intent
或者直到標籤調度系統試完全部可能的 Intent
。
若是沒有應用過濾任何 Intent
,則不執行任何操做
從上咱們也能看出,儘量使用 NDEF
消息和 ACTION_NDEF_DISCOVERED
Intent
,由於它是三種 Intent
中最具體的一種。與其餘兩種 Intent
相比,此 Intent
可以使您在更恰當的時間啓動應用,從而爲用戶帶來更好的體驗
用於訪問 NFC
硬件的 NFC <uses-permission>
元素
<uses-permission android:name="android.permission.NFC" />
複製代碼
API 級別 9
僅經過 ACTION_TAG_DISCOVERED
支持有限的標籤調度,可是如今target API
都到30
了,因此這塊基本不須要修改
<uses-feature android:name="android.hardware.nfc" android:required="true" />
複製代碼
ACTION_NDEF_DISCOVERED
如下示例展現瞭如何過濾 MIME 類型爲 text/plain
的 ACTION_NDEF_DISCOVERED
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>
複製代碼
如下示例展現瞭如何過濾採用 https://developer.android.com/index.html
形式的 URI
<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
資源文件,用它在 tech-list
集內指定您的 Activity
所支持的技術。若是 tech-list
集是標籤所支持的技術(可經過調用 getTechList()
來獲取)的子集
如下示例定義了全部技術。您能夠移除本身不須要的技術。將此文件(你能夠隨便命名)保存到 <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>
複製代碼
如下示例展現瞭如何與支持 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>
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
複製代碼
最後清單文件中添加
<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>
複製代碼
ACTION_TAG_DISCOVERED
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
複製代碼
若是某個 Activity
因爲 NFC
Intent
而啓動,您能夠從該 Intent
中獲取有關掃描到的 NFC
標籤的信息。Intent
能夠包含如下 extra
,具體取決於掃描到的標籤
EXTRA_TAG
(必需):一個 Tag
對象,表示掃描到的標籤
EXTRA_NDEF_MESSAGES
(可選):從標籤中解析出的一組 NDEF
消息。此 extra
對於 ACTION_NDEF_DISCOVERED
Intent
而言是必需的
EXTRA_ID
(可選):標籤的低級別 ID