您在应用清单中注册的意图过滤器没有多大意义。
-
android.nfc.action.TAG_DISCOVERED(在清单中使用时)只是一种备用机制,用于捕获其他应用无法处理的任何 NFC 标签。
-
android.nfc.action.NDEF_DISCOVERED 还需要一个数据类型规范来实际捕获包含 特定 NDEF 记录的 NFC 标签。它不会匹配没有标签的任何标签。
-
android.nfc.action.TECH_DISCOVERED 还需要一种技术来捕捉特定的标签技术。它不会匹配没有标签的任何标签。
此外,您可能希望将每个意图操作放在单独的 <intent-filter> 中,以便更好地控制类别、数据类型等。
但是,由于您只对在您的 Activity 处于前台时接收 NFC 发现事件感兴趣,因此您有更好且(在某种程度上)更可靠的选项来检测标签:前台调度系统和阅读器模式 API。
您可能希望在其中一个中进行选择:
- 如果您使用的是 Android 4.4+ 并且您只对检测其他标签(以及 no 点对点模式设备)感兴趣。我强烈建议您使用阅读器模式 API,因为它可以让您更好地控制要检测的标签以及应如何处理这些标签。此外,如果您希望能够检测另一台 Android 设备上的 HCE 应用程序并与之对话,那么您唯一的选择就是阅读器模式 API。
- 如果您还想支持 Android 4.4 之前的设备,或者您还想从点对点设备接收数据(例如通过 Android Beam),则需要坚持使用前台调度系统。
前台调度系统
您可以在onResume() 期间注册您的活动以接收 NFC 意图:
@Override
public void onResume() {
super.onResume();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
在 Kotlin 中可能是这样的(虽然没有测试):
fun onResume() {
super.onResume()
val pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null)
}
确保在onPause() 期间再次取消注册:
@Override
public void onPause() {
super.onPause();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.disableForegroundDispatch(this);
}
科特林:
fun onPause() {
super.onPause()
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
nfcAdapter.disableForegroundDispatch(this)
}
然后,您将通过onNewIntent() 接收作为 TAG_DISCOVERED 意图的 NFC 事件:
@Override
public void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
// TODO: process intent
}
}
科特林:
fun onNewIntent(intent: Intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
// TODO: process intent
}
}
阅读器模式 API
使用阅读器模式 API,您可以在 onStart() 期间注册您的活动以接收 NFC 回调(此处未使用意图!):
@Override
public void onStart() {
super.onStart();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback() {
@Override
public void onTagDiscovered(Tag tag) {
// TODO: use NFC tag
}
}, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NFC_BARCODE, null);
}
科特林:
fun onStart() {
super.onStart()
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
nfcAdapter.enableReaderMode(this, object : NfcAdapter.ReaderCallback() {
fun onTagDiscovered(tag: Tag) {
// TODO: use NFC tag
}
}, NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or NfcAdapter.FLAG_READER_NFC_BARCODE, null)
}
您还应该确保在onStop()期间取消注册:
@Override
public void onStop() {
super.onStop();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.disableReaderMode(this);
}
科特林:
fun onStop() {
super.onStop()
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
nfcAdapter.disableReaderMode(this)
}
您通过上面的onTagDiscovered(Tag tag) 回调方法接收发现的标签句柄。相反,您当然也可以在您的活动类上实现NfcAdapter.ReaderCallback 接口,并将this 而不是匿名类传递给enableReaderMode 方法。