NFC高級

高級 NFC


本文檔介紹了高級的NFC主題,如各種標籤技術,NFC標籤寫入和前臺發佈,它允許即使當其他應用程序過濾器相同的時候,應用程序在前臺處理Intent。

Tag技術支持工作



當使NFC Tag和Android的供電設備生效,使用Tag來讀取和寫入數據的主要格式是NDEF,當設備掃描NDEF數據的Tag,Android提供支持解析的消息,並在可能的情況下將它傳入一個NdefMessage,但是,在有些情況下,當你掃描不包含NDEF數據的Tag或當NDEF數據時無法映射到MIME類型或URI時。在那樣的情況下,你需要直接與Tag建立溝通及用自己的協議(在原始字節)讀寫它,Android用android.nfc.tech包對那些情況提供了通用的支持,如表1中所描述的。您可以使用getTechList()方法來確定技術支持Tag,並且用由android.nfc.tech提供的類的其中一個創建相應TagTechnology對象.

表 1. 支持的Tag技術

描述
TagTechnology 這個接口是下面所有tag technology類必須實現的。
NfcA 提供訪問 NFC-A (ISO 14443-3A) 的屬性和 I/O 操作
NfcB 提供訪問 NFC-B (ISO 14443-3B) 的屬性和 I/O 操作
NfcF 提供訪問 NFC-F (JIS 6319-4) 的屬性和 I/O 操作
NfcV 提供訪問 NFC-V (ISO 15693)  的屬性和 I/O 操作
IsoDep 提供訪問 ISO-DEP (ISO 14443-4) 的屬性和 I/O 操作
Ndef 提供對那些被格式化爲NDEFtag的數據的訪問和其他操作
NdefFormatable 對那些可以被格式化成NDEF格式的tag提供一個格式化的操作

下面的Tag技術不要求被Android的供電設備支持。

表 2. 可選的支持的Tag技術

描述
MifareClassic 如果android設備支持MIFARE,提供對MIFARE Classic目標的屬性和I/O操作。
MifareUltralight 如果android設備支持MIFARE,提供對MIFARE Ultralight目標的屬性和I/O操作。

Tag技術工作和 ACTION_TECH_DISCOVERED Intent


當一個設備掃描一個有NDEF數據的Tag,但不能被映射到一個MIME或URI時,Tag發佈系統試圖啓動一個Activity與ACTION_TECH_DISCOVERED Intent。當非NDEF被掃描到時,ACTION_TECH_DISCOVERED的Tag也可以使用.如果Tag發佈系統無法爲你解析它,此回退讓你直接進行掃描標籤上的數據,基本步驟與標籤技術如下:

  1. 過濾一個你想要處理的Tag技術的 ACTION_TECH_DISCOVERED intent. 獲取更多信息請參閱 過濾 NFC intents. 一般來說。 當一個NDEF消息不能被映射到MIME類型或者URI上時,Tag發佈系統嘗試啓動一個ACTION_TECH_DISCOVERED intent, 否則如果被掃描到的Tag不包含NDEF數據. 欲瞭解如何確定的更多信息,請參閱Tag發佈系統.
  2. 當你的應用程序接收到該Intent, 從以圖中獲取Tag對象:
    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  3. 通過調用在android.nfc.tech包的類中的一個get factory方法,獲取到TagTechnology的一個實例 . 你可以在調用一個get factory方法以前,計算支持Tag技術通過調用getTechList(). 舉例來說, 爲了從一個Tag得到MifareUltralight的一個實例, 請執行下列操作:
    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));

讀取和寫入Tags


讀取和寫入NFC tag涉及到從Intent中獲取到Tag並創建與tag的連接. 你必須定義你自己的協議來讀寫數據到Tag. 然後,記住當直接使用Tag時你仍然能夠讀寫NDEF數據. 你想要如何構建東西,它可以實現. 如下的例子演示如何使用一個MIFARE Ultralight tag.

package com.example.android.nfc;

import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;

public class MifareUltralightTagTester {

    private static final String TAG = MifareUltralightTagTester.class.getSimpleName();

    public void writeTag(Tag tag, String tagText) {
        MifareUltralight ultralight = MifareUltralight.get(tag);
        try {
            ultralight.connect();
            ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII")));
        } catch (IOException e) {
            Log.e(TAG, "IOException while closing MifareUltralight...", e);
        } finally {
            try {
                ultralight.close();
            } catch (IOException e) {
                Log.e(TAG, "IOException while closing MifareUltralight...", e);
            }
        }
    }

    public String readTag(Tag tag) {
        MifareUltralight mifare = MifareUltralight.get(tag);
        try {
            mifare.connect();
            byte[] payload = mifare.readPages(4);
            return new String(payload, Charset.forName("US-ASCII"));
        } catch (IOException e) {
            Log.e(TAG, "IOException while writing MifareUltralight
            message...", e);
        } finally {
            if (mifare != null) {
               try {
                   mifare.close();
               }
               catch (IOException e) {
                   Log.e(TAG, "Error closing tag...", e);
               }
            }
        }
        return null;
    }
}

使用前端發佈系統



前端發佈系統允許一個activity攔截一個 intent並且要求由於其他處理同樣intent的activities. 使用這個系統涉及到爲了Android系統能夠發送合適的intents給你的應用程序而構建幾個數據結構. 爲了使前端發佈系統有效:

  1. 在你的activity的 onCreate()方法中添加如下代碼:
    1. 創建一個 PendingIntent 對象, 以便系統可以在它被掃描到時,用tag的細節填充它
      PendingIntent pendingIntent = PendingIntent.getActivity(
          this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    2. 在Intent filters裏聲明你想要處理的Intent,一個tag被檢測到時先檢查前臺發佈系統,如果前臺Activity符合Intent filter的要求,那麼前臺的Activity的將處理此Intent。如果不符合,前臺發佈系統將Intent轉到Intent發佈系統。如果指定了null的Intent filters,當任意tag被檢測到時,你將收到TAG_DISCOVERED intent。下面的代碼片斷處理所有NDEF_DISCOVERED的MIME類型. 因此請注意你應該只處理你想要的Intent。
      IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
          try {
              ndef.addDataType("*/*");    /* Handles all MIME based dispatches.
                                             You should specify only the ones that you need. */
          }
          catch (MalformedMimeTypeException e) {
              throw new RuntimeException("fail", e);
          }
         intentFiltersArray = new IntentFilter[] {ndef, };
    3. 設置一個你程序要處理的Tag technologies的列表,調用Object.class.getName() 方法來獲得你想要支持處理的technology類。
      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
  2. 覆蓋下面的方法來打開或關閉前臺發佈系統。比如onPause()onResume()方法。必須在主線程裏調用enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][]) 而且Activity在前臺(可以在onResume()裏調用來保證這點)。你也要覆蓋onNewIntent回調來處理得到的NFC tag數據。
    public void onPause() {
        super.onPause();
        mAdapter.disableForegroundDispatch(this);
    }
    
    public void onResume() {
        super.onResume();
        mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
    }
    
    public void onNewIntent(Intent intent) {
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        //do something with tagFromIntent
    }
從API Demos獲取完整的示例演示ForegroundDispatch例子
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章