You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 19:16:05