Android开发:捕获NFC消息后停止扫描,移除标签后恢复扫描
解决NFC重复扫描同一标签的问题
要实现“捕获标签后停止扫描,移除后恢复”,核心是控制NFC前台调度的启用/禁用,同时监听标签的连接状态判断用户是否移除了标签。以下是具体改造方案:
第一步:添加成员变量
在你的NFC相关Activity或处理类中,添加全局变量保存标签状态和调度控制器:
private var currentNdef: Ndef? = null private var nfcAdapter: NfcAdapter? = null private var pendingIntent: PendingIntent? = null private var intentFiltersArray: Array<IntentFilter>? = null private var techListsArray: Array<Array<String>>? = null
第二步:初始化前台调度参数
在Activity的onCreate方法中完成NFC基础配置:
nfcAdapter = NfcAdapter.getDefaultAdapter(this) pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE ) val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED) try { ndef.addDataType("*/*") } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException("Failed to add MIME type", e) } intentFiltersArray = arrayOf(ndef) techListsArray = arrayOf(arrayOf(Ndef::class.java.name))
第三步:改造onTagDiscovered方法
修改标签发现逻辑,处理完标签后停止调度,监听移除事件后恢复:
override fun onTagDiscovered(tag: Tag?) { tag ?: return try { val mNdef = Ndef.get(tag) currentNdef = mNdef val ndefMessage = mNdef.cachedNdefMessage // 提取URL并处理业务逻辑 for (curRecord in ndefMessage.records) { curRecord.toUri()?.let { uri -> val text = uri.toString() processNfcTag(text) break } } // 处理完成后立即停止NFC前台调度,避免重复触发 nfcAdapter?.disableForegroundDispatch(this) // 启动线程监听标签连接状态 Thread { while (true) { try { // 检查标签是否仍保持连接 if (!mNdef.isConnected) { // 标签已移除,恢复前台调度 runOnUiThread { nfcAdapter?.enableForegroundDispatch( this, pendingIntent, intentFiltersArray, techListsArray ) } currentNdef = null break } Thread.sleep(500) // 每隔500ms检查一次 } catch (e: Exception) { // 连接异常时视为标签已移除,恢复调度 runOnUiThread { nfcAdapter?.enableForegroundDispatch( this, pendingIntent, intentFiltersArray, techListsArray ) } currentNdef = null break } } }.start() } catch (e: Exception) { // 读取失败时不停止调度,允许重新扫描 e.printStackTrace() } }
关键逻辑说明
- 禁用前台调度:处理完标签后调用
disableForegroundDispatch,NFC系统将不再触发标签发现事件,直到重新启用。 - 监听连接状态:通过
Ndef.isConnected()判断标签是否仍与设备连接,用线程定时检查避免阻塞UI。 - 恢复调度:检测到标签断开(用户移除)后,在UI线程调用
enableForegroundDispatch恢复扫描。
补充:生命周期处理
在Activity的生命周期方法中维护调度状态,避免后台占用NFC资源:
override fun onResume() { super.onResume() nfcAdapter?.enableForegroundDispatch( this, pendingIntent, intentFiltersArray, techListsArray ) } override fun onPause() { super.onPause() nfcAdapter?.disableForegroundDispatch(this) }
改造后,应用会在捕获标签后立即停止扫描,用户移除标签后自动恢复,彻底解决重复弹窗问题。
内容的提问来源于stack exchange,提问作者androoby
相关产品推荐
相关产品推荐

