这篇文章只讲NFC读写非接卡、读写标签的方式,且这里只讲符合TypeA和IsoDep技术标准的Tag,其他类型的Tag框架类似,只是有些许差别
添加权限
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>
添加过滤列表
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相关
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
public static String[][] TECHLISTS; //NFC技术列表
public static IntentFilter[] FILTERS; //过滤器
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触发
@Override
protected void onNewIntent(Intent intent) {
//从intent中获取标签信息
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(); // 关闭连接
}
}
}
//程序恢复
@Override
protected void onResume() {
super.onResume();
if (nfcAdapter != null) {
// 这行代码是添加调度,效果是读标签的时候不会弹出候选程序,直接用本程序处理
nfcAdapter.enableForegroundDispatch(this, pendingIntent, FILTERS, TECHLISTS);
}
}
//程序暂停
@Override
protected void onPause() {
if (nfcAdapter != null)
nfcAdapter.disableForegroundDispatch(this); // 取消调度
}
}
使用NFC读写Tag主要流程是:
设置系统调度 -> 系统调用onNewIntent(Intent intent)
-> 获取Tag -> 获取读写通道 -> 进行读写 -> 最后取消系统调度
读写Tag流程:
- 建立连接
- 读写
- 关闭连接
需要注意的是有些卡片关闭连接后再次建立连接会重置内部状态,具体参照卡片特性来定具体的读写方式。
附一张系统的调度图: