這篇文章只講NFC讀寫(xiě)非接卡、讀寫(xiě)標(biāo)簽的方式,且這里只講符合TypeA和IsoDep技術(shù)標(biāo)準(zhǔn)的Tag,其他類(lèi)型的Tag框架類(lèi)似,只是有些許差別
添加權(quán)限
AndroidManifests.xml中添加:
<uses-permission android:name="android.permission.NFC"/>
添加intent filter
AndroidManifests.xml中添加:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustUnspecified|stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<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>
添加過(guò)濾列表
res/xml文件夾下新建nfc_tech_filter.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
</resources>
Activity
先直接貼代碼:
public class MainActivity extends AppCompatActivity {
// NFC相關(guān)
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
public static String[][] TECHLISTS; //NFC技術(shù)列表
public static IntentFilter[] FILTERS; //過(guò)濾器
static {
try {
TECHLISTS = new String[][] { { IsoDep.class.getName() }, { NfcA.class.getName() } };
FILTERS = new IntentFilter[] { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED, "*/*") };
} catch (Exception ignored) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
onNewIntent(getIntent());
}
//處理NFC觸發(fā)
@Override
protected void onNewIntent(Intent intent) {
//從intent中獲取標(biāo)簽信息
Parcelable p = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (p != null) {
Tag tag = (Tag) p;
isodep = IsoDep.get(tag);
if (isodep != null){
isoDep.connect(); // 建立連接
byte[] data = new byte[20];
byte[] response = isoDep.transceive(data); // 傳送消息
isoDep.close(); // 關(guān)閉連接
}
}
}
//程序恢復(fù)
@Override
protected void onResume() {
super.onResume();
if (nfcAdapter != null) {
// 這行代碼是添加調(diào)度,效果是讀標(biāo)簽的時(shí)候不會(huì)彈出候選程序,直接用本程序處理
nfcAdapter.enableForegroundDispatch(this, pendingIntent, FILTERS, TECHLISTS);
}
}
//程序暫停
@Override
protected void onPause() {
if (nfcAdapter != null)
nfcAdapter.disableForegroundDispatch(this); // 取消調(diào)度
}
}
使用NFC讀寫(xiě)Tag主要流程是:
設(shè)置系統(tǒng)調(diào)度 -> 系統(tǒng)調(diào)用onNewIntent(Intent intent) -> 獲取Tag -> 獲取讀寫(xiě)通道 -> 進(jìn)行讀寫(xiě) -> 最后取消系統(tǒng)調(diào)度
讀寫(xiě)Tag流程:
- 建立連接
- 讀寫(xiě)
- 關(guān)閉連接
需要注意的是有些卡片關(guān)閉連接后再次建立連接會(huì)重置內(nèi)部狀態(tài),具體參照卡片特性來(lái)定具體的讀寫(xiě)方式。
附一張系統(tǒng)的調(diào)度圖:

nfc_tag_dispatch.png