我根本不熟悉NFC标签检测,而且我试图为活动中检测到的任何NFC标签设置监听器。我想在活动检测到NFC标签时只显示一个Toast消息,但我很难这样做。
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity)
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
Toast.makeText(applicationContext, "NFC Tag Detected", Toast.LENGTH_LONG).show()
}
在我的清单中,我有这个:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
我正在使用三星Galaxy S6和S7进行测试。当我把它们放在一起,而活动在其中一个上运行时,我希望能够看到一个祝酒词,但到目前为止还没有任何东西出现。我不需要阅读标签,我不关心它是什么类型的标签,我只需要知道检测到标签。
答案 0 :(得分:2)
您在应用清单中注册的意图过滤器没有多大意义。
android.nfc.action.TAG_DISCOVERED
(在清单中使用时)只是一种后备机制,可以捕获任何其他应用未处理的NFC标记。android.nfc.action.NDEF_DISCOVERED
还需要一个数据类型规范来实际捕获包含特定 NDEF记录的NFC标记。如果没有一个标签,它将无法匹配。android.nfc.action.TECH_DISCOVERED
还需要一种技术来捕捉特定的标签技术。如果没有一个标签,它将无法匹配。此外,您可能希望将每个意图操作放在单独的<intent-filter>
中,以便更好地控制类别,数据类型等。
但是,由于您只对在活动位于前台时接收NFC发现事件感兴趣,因此您可以更好地(有些)更可靠地检测标记:前景调度系统和阅读器模式API。
您可能希望在其中一个中进行选择:
您可以在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,您可以在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
方法。