高級NFC

文章譯自:Advanced NFC 

本文檔介紹了高級NFC,如與各種標籤技術協作,NFC標籤寫入和前臺調度,它允許應用程序在前臺處理的intent,即使當其他應用程序過濾器相同的。

標籤技術支持工作

當NFC標籤和Android工作時,使用讀取和寫入數據的的主要格式是NDEF標籤。當設備掃描標籤NDEF數據,Android提供瞭解析NdefMessage消息和其他可能的支持。當掃描標籤不包含NDEF數據或NDEF數據不能被映射到一個MIME類型或UR時,在這些情況下,你需要打開tag並直接與其信息交換和使用自己的協議讀寫數據(在原始字節)。Android爲使用的android.nfc.tech包情況提供了通用的支持,android.nfc.tech包如表1中所描述的 。您可以使用的getTechList()方法來確定標籤的技術支持,並建立 與之一由android.nfc.tech類相應TagTechnology對象。

Table 1. Supported tag technologies

Class Description
TagTechnology 所有標籤技術類必須實現的接口。
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 提供NFC標籤已被格式化爲NDEF的數據和操作的訪問。
NdefFormatable 提供可能被格式化爲NDEF的 formattable的標籤。

下面的tag技術並不強制android設備支持(即選擇性的支持)。

Table 2. Optional supported tag technologies

Class Description
MifareClassic 如果此Android設備支持MIFARE,提供訪問的MIFARE Classic性能和I / O操作。
MifareUltralight 如果此Android設備支持MIFARE,提供訪問的MIFARE 超輕性能和I / O操作。

Tag技術與ACTION_TECH_DISCOVERED intent間協作

當設備掃描含有NDEF數據的tag,但不能被映射到一個MIME或URI,標籤調度系統試圖啓動一個攜帶ACTION_TECH_DISCOVERED intent的activity。 掃描tag不是NDEF數據格式時,ACTION_TECH_DISCOVERED也可使用。有這種東西,如果標籤調度系統無法解析tag時,可以直接與tag上數據進行交互。tag技術工作時的基本步驟如下:
1、過濾指定要處理的標籤技術的ACTION_TECH_DISCOVERED intent。在一般情況下,標籤調度系統嘗試啓動一個ACTION_TECH_DISCOVERED的intent,當NDEF消息,不能被映射爲MIME類型或URI,或者如果標籤掃描不包含NDEF數據。如何確定欲瞭解更多信息,請參閱標籤調度系統。
2、當你的應用程序接收的intent,取得標籤對象:

Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
3、獲得實例的TagTechnology,通過調用android.nfc.tech包 的get方法。調用get方法前,通過調用getTechList()可以列舉tag支持的技術。例如,從tag中要獲得一個實例MifareUltralight,可以如下做:

MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));

Tags讀寫

NFC標籤讀寫必須確保獲得intent並打開tag間通信。爲了讀取和寫入數據到標籤,您必須定義自己的協議棧。請記住,當直接與tag交互時,你仍然可以讀取寫NDEF格式的數據。它依賴你怎麼去構建。下面的例子顯示瞭如何使用一個MIFARE超輕標籤。

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的activity的優先級要高。使用這個系統可以爲android系統構建一些數據結構,數據結構能夠爲應用程序發送適當的意圖。爲了使前景調度系統:
1、在activity的onCreate()方法中添加如下code:
 a、創建一個PendingIntent對象,android系統可以填充在tag被掃描到的內容。
PendingIntent pendingIntent = PendingIntent.getActivity(
 this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
b、聲明intent過濾器來處理你想攔截的intent。前臺調度系統檢查過濾指定的intent,這個intent是掃描標籤時收到的。如果匹配,那麼你的應用程序處理的意圖。如果它不匹配,前臺調度系統回到intent調度系統的。指定一個空的數組intent過濾器和技術過濾器,指定要過濾所有的標籤,回到TAG_DISCOVERED  intent。下面的代碼片段處理所有MIME類型NDEF_DISCOVERED。您應該只處理那些你需要的。
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, };
c、設置您的應用程序要處理tag技術的數組。調用 Object.class.getName()方法來獲取支持的所以技術。
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };

2、重寫以下activity生命週期回調函數,當activity失去(onPause())和恢復(onResume())焦點時,添加邏輯啓用和禁用前臺調度。enableForegroundDispatch()必須主線程調用,並只有當activity在前臺(調用onResume()保證這一點)。您還需要實現onNewIntent回調函數來處理掃描NFC標籤的數據。
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 demo中的ForegroundDispatch部分。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章