Android支持的數據格式
數據格式的Intent filter
AndroidManifest.xml文件中,要像向下列示例那樣,在<activity>元素內的<meta-data>元素中指定你創建的資源文件:
- <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>
nfc_tech_filter.xml文件(一個Tag標簽只有全部匹配tech-list元素中的tech元素指定的nfc芯片時才認為被匹配):
- <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>
也可創建多個資源文件(多個資源文件是OR關系,每個資源文件中的芯片是AND關系):
- <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>android.nfc.tech.NdefFormatable</tech>
- </tech-list>
- </resources>
- <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <tech-list>
- <tech>android.nfc.tech.Ndef</tech>
- <tech>android.nfc.tech.NdefFormatable</tech>
- </tech-list>
- </resources>
或者在同一個資源文件中創建多個<tech-list>元素(多個<tech-list>元素之間是OR關系,<tech-list>元素中的<tech>是AND關系):
- <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <tech-list>
- <tech>android.nfc.tech.NfcA</tech>
- </tech-list>
- <tech-list>
- <tech>android.nfc.tech.NfcB</tech>
- </tech-list>
- <tech-list>
- <tech>android.nfc.tech.MifareClassic</tech>
- </tech-list>
- </resources>
查看標簽支持數據格式的方法:
通過Tag.getTechlist()方法,獲得標簽所支持的數據格式
通過Tag.getId()方法,獲得標簽的唯一ID標識
NfcAdapter == null:表示設備不支持NFC硬件
NfcAdapter.isEnable()方法:判斷NFC是否開啟
綜上所述:
一個Tag通過Tag.getTechlist()方法獲取它所支持的所有標簽類型,如果清單文件中所引用的<tech-list>資源文件中所有的<tech>中的芯片是Tag標簽所有支持標簽的子集則被匹配的,可以寫多個<tech-list>,每個<tech-list>時獨立的,只要有其中一個<tech-list>中的所有的<tech>中的芯片類型全部匹配Tag所支持的芯片則認為是匹配的。多個<tech-list>是OR關系,<tech-list>中的<tech>是AND關系。
MifareClassic標簽的外形結構
MifareClassic標簽的數據結構
注意事項(假設1k空間):
第一扇區的第一塊一般用於制造商占用塊
0-15個扇區:一個扇區對應4個塊,所以總共有64個塊,序號分別為0-63,第一個扇區對應:0-3塊,第二個扇區對應:4-7塊...
每個扇區的最后一個塊用來存放密碼或控制位,其余為數據塊,一個塊占用16個字節,keyA占用6字節,控制位占用4字節,keyB占用6字節
MifareClassic類的常用方法
get():根據Tag對象來獲得MifareClassic對象;
Connect():允許對MifareClassic標簽進行IO操作;
getType():獲得MifareClassic標簽的具體類型:TYPE_CLASSIC,TYPE_PLUA,TYPE_PRO,TYPE_UNKNOWN;
getSectorCount():獲得標簽總共有的扇區數量;
getBlockCount():獲得標簽總共有的的塊數量;
getSize():獲得標簽的容量:SIZE_1K,SIZE_2K,SIZE_4K,SIZE_MINI
authenticateSectorWithKeyA(int SectorIndex,byte[] Key):驗證當前扇區的KeyA密碼,返回值為ture或false。
常用KeyA:默認出廠密碼:KEY_DEFAULT,
各種用途的供貨商必須配合該技術的MAD:KEY_MIFARE_APPLICATION_DIRECTORY
被格式化成NDEF格式的密碼:KEY_NFC_FORUM
getBlockCountInSector(int):獲得當前扇區的所包含塊的數量;
sectorToBlock(int):當前扇區的第1塊的塊號;
writeBlock(int,data):將數據data寫入當前塊;注意:data必須剛好是16Byte,末尾不能用0填充,應該用空格
readBlock(int):讀取當前塊的數據。
close():禁止對標簽的IO操作,釋放資源。
MifareClassic標簽的讀寫流程
獲得Adapter對象
獲得Tag對象
獲得MifareClassic對象
讀取數據塊的數據
Connect(),readBlock(),close()
獲得Adapter對象
獲得Tag對象
獲得MifareClassic對象
將數據塊寫入標簽
Connect(),writeBlock(),close()
官方文檔:
Working with tag technologies and the ACTION_TECH_DISCOVERED intent
When a device scans a tag that has NDEF data on it, but could not be mapped to a MIME or URI, the tag dispatch system tries to start an activity with the ACTION_TECH_DISCOVERED
intent. The ACTION_TECH_DISCOVERED
is also used when a tag with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag directly if the tag dispatch system could not parse it for you. The basic steps when working with tag technologies are as follows:
- Filter for an
ACTION_TECH_DISCOVERED
intent specifying the tag technologies that you want to handle. SeeFiltering for NFC intents for more information. In general, the tag dispatch system tries to start aACTION_TECH_DISCOVERED
intent when an NDEF message cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For more information on how this is determined, see The Tag Dispatch System. - When your application receives the intent, obtain the
Tag
object from the intent:Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Obtain an instance of a
TagTechnology
, by calling one of theget
factory methods of the classes in theandroid.nfc.tech
package. You can enumerate the supported technologies of the tag by callinggetTechList()
before calling aget
factory method. For example, to obtain an instance ofMifareUltralight
from aTag
, do the following:MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Reading and writing to tags
Reading and writing to an NFC tag involves obtaining the tag from the intent and opening communication with the tag. You must define your own protocol stack to read and write data to the tag. Keep in mind, however, that you can still read and write NDEF data when working directly with a tag. It is up to you how you want to structure things. The following example shows how to work with a 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