Android NFC開發詳細介紹一(理論篇)

大家在做nfc開發之前可以看一下我的上篇文章區分IC卡和ID卡

Near Field Communication (NFC) 爲一短距離無線通信技術,通常有效通訊距離爲4釐米以內。NFC工作頻率爲13.65 兆赫茲,通信速率爲106 kbit/秒到 848kbit/秒,NFC手機相比普通手機來說,NFC整合了非接觸式讀卡器、非接觸式智能卡和點對點(Peer-to—Peer)通信功能,爲消費者開創了全新的便捷生活方式。手機和NFC技術的結合,將會給消費者提供極大的生活便利,例如移動支付、位置服務信息、身份識別、公共交通卡等應用,在醫療保健、優惠券、智能海報等許多領域有也有巨大的應用潛力。

一 、nfc的三種工作模式

這裏給出官方文檔的鏈接 大家可以看一下

  1. 讀卡器模式
    數據在NFC芯片中,可以簡單理解成“刷標籤”。本質上就是通過支持NFC的手機或其它電子設備從帶有NFC芯片的標籤、貼紙、名片等媒介中讀寫信息。通常NFC標籤是不需要外部供電的。當支持NFC的外設向NFC讀寫數據時,它會發送某種磁場,而這個磁場會自動的向NFC標籤供電。

  2. 仿真卡模式
    數據在支持NFC的手機或其它電子設備中,可以簡單理解成“刷手機”。本質上就是將支持NFC的手機或其它電子設備當成借記卡、公交卡、門禁卡等IC卡使用。基本原理是將相應IC卡中的信息憑證封裝成數據包存儲在支持NFC的外設中 。
    在使用時還需要一個NFC射頻器(相當於刷卡器)。將手機靠近NFC射頻器,手機就會接收到NFC射頻器發過來的信號,在通過一系列複雜的驗證後,將IC卡的相應信息傳入NFC射頻器,最後這些IC卡數據會傳入NFC射頻器連接的電腦,並進行相應的處理(如電子轉帳、開門等操作)。

  3. 點對點模式
    該模式與藍牙、紅外差不多,用於不同NFC設備之間進行數據交換,不過這個模式已經沒有有“刷”的感覺了。其有效距離一般不能超過4釐米,但傳輸建立速度要比紅外和藍牙技術快很多,傳輸速度比紅外塊得多,如過雙方都使用Android4.2,NFC會直接利用藍牙傳輸。這種技術被稱爲Android Beam。所以使用Android Beam傳輸數據的兩部設備不再限於4釐米之內。
    點對點模式的典型應用是兩部支持NFC的手機或平板電腦實現數據的點對點傳輸,例如,交換圖片或同步設備聯繫人。因此,通過NFC,多個設備如數字相機,計算機,手機之間,都可以快速連接,並交換資料或者服務。

花了點時間,下面用表格寫出NFC、藍牙和紅外之間的差異:

對比項 NFC 藍牙 紅外
網絡類型 點對點 單點對多點 點對點
有效距離 <=0.1m <=10m,最新的藍牙4.0有效距離可達100m 一般在1m以內,熱技術連接,不穩定
傳輸速度 最大424kbps 24Mbps 最大慢速115.2kbps,快速4Mbps
建立時間 <0.1s 6s 0.5s
安全性 安全,硬件實現 安全,軟件實現 不安全,使用IRFM時除外
通信模式 主動-主動/被動 主動-主動 主動-主動
成本

二、Android對NFC的支持

不同的NFC標籤之間差異很大,有的只支持簡單的讀寫操作,有時還會採用支持一次性寫入的芯片,將NFC標籤設計成只讀的。當然,也存在一些複雜的NFC標籤,例如,有一些NFC標籤可以通過硬件加密的方式限制對某一區域的訪問。還有一些標籤自帶操作環境,允許NFC設備與這些標籤進行更復雜的交互。這些標籤中的數據也會採用不同的格式。
==但Android SDK API主要支持NFC論壇標準(Forum Standard),這種標準被稱爲NDEF(NFC Data Exchange Format,NFC數據交換格式)==

三、API概覽 Class Description

Class Description
NfcManager 一個NFC adapter的管理器,可以列出所有此android設備支持的NFC adapter.只不過大部分android 設備只有一個NFC adapter,所以你大部分情況下可以直接用靜態方法 getDefaultAdapter(context)來取適配器。
NfcAdapter 表示本設備的NFC adapter,可以定義Intent來請求將系統檢測到tags的提醒發送到你的Activity.並提供方法去註冊前臺tag提醒發佈和前臺NDEF推送。 前臺NDEF推送是當前android版本唯一支持的p2p NFC通信方式。
NdefMessage,NdefRecord NDEF是NFC論壇定義的數據結構,用來有效的存數據到NFC tags.比如文本,URL,和其他MIME類型。一個NdefMessage扮演一個容器,這個容器存哪些發送和讀到的數據。一個NdefMessage對象包含0或多個NdefRecord,每個NDEF record有一個類型,比如文本,URL,智慧型海報/廣告,或其他MIME數據。在NDEFMessage裏的第一個NfcRecord的類型用來發送tag到一個android設備上的activity.
Tag 標示一個被動的NFC目標,比如tag,card,鑰匙掛扣,甚至是一個電話模擬的的NFC卡. 當一個tag被檢測到,一個tag對象將被創建並且封裝到一個Intent裏,然後NFC 發佈系統將這個Intent用startActivity發送到註冊了接受這種Intent的activity裏。你可以用getTechList()方法來得到這個tag支持的技術細節和創建一個android.nfc.tech提供的相應的TagTechnology對象。

四、Tag支持的技術標準

Class Description
TagTechnology 這個接口是下面所有tag technology類必須實現的。
NfcA 支持ISO 14443-3A 標準的操作。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 提供對那些被格式化爲NDEF的tag的數據的訪問和其他操作。 Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
NdefFormatable 對那些可以被格式化成NDEF格式的tag提供一個格式化的操作
MifareClassic 如果android設備支持MIFARE,提供對MIFARE Classic目標的屬性和I/O操作。
MifareUltralight 如果android設備支持MIFARE,提供對MIFARE Ultralight目標的屬性和I/O操作。

五、Tag發佈系統

當android設備掃描到一個NFC tag,通用的行爲是自動找最合適的Activity會處理這個tag Intent而不需要用戶來選擇哪個Activity來處理。因爲設備掃描NFC tags是在很短的範圍和時間,如果讓用戶選擇的話,那就有可能需要移動設備,這樣將會打斷這個掃描過程。你應該開發你只處理需要處理的tags的Activity,以防止讓用戶選擇使用哪個Activity來處理的情況。Android提供兩個系統來幫助你正確的識別一個NFC tag是否是你的Activity想要處理的:Intent發佈系統和前臺Activity發佈系統。

Intent發佈系統檢查所有Activities的intent filters,找出那些定義了可以處理此tag的Activity,如果有多個Activity都配置了處理同一個tag Intent,那麼將使用Activity選擇器來讓用戶選擇使用哪個Activity。用戶選擇之後,將使用選擇的Activity來處理此Intent.

前臺發佈系統允許一個Activity覆蓋掉Intent發佈系統而首先處理此tag Intent,這要求你將要處理Tag Intent的Activity運行在前臺,這樣當一個NFC tag被掃描到,系統先檢測前臺的Activity是否支持處理此Intent,如果支持,即將此Intent傳給此Activity,如果不支持,則轉到Intent發佈系統。

5.1使用Intent發佈系統

Intent發佈系統指定了3個intent有不同的優先級。通常當一個tag被檢測到之後,Intent就被啓動(start)了,這個啓動遵循以下行爲

  • android.nfc.action.NDEF_DISCOVERED: 這個intent是在一個包含NDEF負載的tag被檢測到時啓動,這是最高優先級的intent, android系統不會讓你指定一個Intent能處理所有的NFC數據類型,你必須在AndroidManifest.xml中指定與NFC tag對應的元素,這樣當掃描到的tag傳過來的數據類型與你定義的相匹配時,你的Activity就會被調用。
<activity android:name=".NdefActivity"
           android:launchMode="singleTop"
           android:label="NDEF格式"
           > 
           <intent-filter>  
             <action android:name="android.nfc.action.NDEF_DISCOVERED"/>    
             <category android:name="android.intent.category.DEFAULT"/> 
            </intent-filter>
          </activity>

如果NDEF_DISCOVERED intent 已經被啓動,TECH_DISCOVERED 和 TAG_DISCOVERED intents 將不會被啓動。假如一個未知的tag或者不包含NDEF負載的tag被檢測到,此Intent就不會被啓動。

  • android.nfc.action.TECH_DISCOVERED: 如果 NDEF_DISCOVERED intent沒啓動或者沒有一個Activity的filter檢測NDEF_DISCOVERED ,並且此tag是已知的,那麼此TECH_DISCOVERED Intent將會啓動. TECH_DISCOVERED intent要求你在一個資源文件裏(xml)裏指定你要支持technologies列表。
<activity android:name=".MifareClassicActivity"
            android:launchMode="singleTop"
            android:label="讀寫MIFARECLASSIC格式"
            > 
         <intent-filter>
          <action android:name="android.nfc.action.TECH_DISCOVERED"/> 
            <category android:name="android.intent.category.DEFAULT"/> </intent-filter> 
           
            <meta-data  
           android:name="android.nfc.action.TECH_DISCOVERED"
           android:resource="@xml/tech_list"
            />
      </activity>
  • android.nfc.action.TAG_DISCOVERED: 如果沒有一個activity處理_DISCOVERED and TECH_DISCOVERED intents或者tag被檢測爲未知的,那麼此Intent將會被啓動。

假如你的Activity在AndroidManifest.xml文件裏聲明瞭處理android.nfc.action.TECH_DISCOVERED intent ,你必須創建一個Xml格式的資源文件,並加上你的activity支持的technologies到tech-list集合裏。這樣你的activity將被認作能處理這些tech-list的處理者,如果tag使用的technology屬於你的定義的list裏,你的Activity將接收此Intent。你可以用getTechList()來獲得tag支持的technologies。
例如:如果一個tag被檢測到支持MifareClassic, NdefFormatable, 和 NfcA,你的tech-list集合必須指定了其中的一項或者多項來保證你的Activity能處理此Intent。
你也可以指定多個tech-list集合,每個集合都認做獨立的。如果任何單個tech-list集合是getTechList()返回的technologies集合的子集,那麼你的Activity將被認爲匹配了。這個還提供’與’和’或’操作。
tech_filter.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<!--多個<tech-list>元素之間是OR關係,<tech-list>元素中的
<tech>是AND關係,只要任何單個tech-list集合是getTechList()返回的technologies集合的子集,那麼你的Activity將被認爲匹配了--> 

  <tech-list> 
    <tech>android.nfc.tech.Ndef</tech> 
    <tech>android.nfc.tech.MifareClassic</tech> 
</tech-list> 

<!--或--> 

  <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>

5.2使用前臺發佈系統

前臺發佈系統允許一個Activity 攔截一個tag Intent 獲得最高優先級的處理,這種方式很容易使用和實現:

1. 在OnCreate()方法中創建一個 PendingIntent對象, 這樣Android系統就能在一個tag被檢測到時定位到這個對象
PendingIntent pendingIntent = PendingIntent.getActivity(
 this, 0, new Intent(this, getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

==launchMode設爲singleTop,這樣無論NFC標籤靠近手機多少次,保障只有一個Activity實例。(除一次靠近調用OnCreate()方法外,標籤每一次靠近都會調用OnNewIntent()方法。)==

2. 在主線程裏調用enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][])而且Activity在前臺(可以在onResume()裏調用來保證這點)
//頁面獲取到焦點 
  @Override 
  protected void onResume() {
   super.onResume(); 
   if (mNfcAdapter!=null){   
   mNfcAdapter.enableForegroundDispatch(
   this,mPendingIntent,null,null);
 //打開前臺發佈系統,使頁面優於其它nfc處理 
 } 
}
//頁面失去焦點 
@Override 
  protected void onPause() { 
   super.onPause(); 
   if(mNfcAdapter!=null){ 
   mNfcAdapter.disableForegroundDispatch(this);
//關閉前臺發佈系統
 } 
}
3.在OnNewIntent中獲取Tag對象
@Override
protected void onNewIntent(Intent intent) {   
super.onNewIntent(intent); 
 mTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
 String[] techList=mTag.getTechList();  
 System.out.println("標籤支持的tachnology類型:"); 
 for (String tech:techList){ 
 System.out.println(tech); 
 } 
}

以上,是關於NFC的基礎知識,下一篇我們將實現對NFC Ndef標籤和MifareClassic標籤的讀寫操作,大家有什麼意見或問題歡迎留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章