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

Android开发:NFC Tag Intent始终为空问题求助

NFC读取时Tag为空的排查与修复方案

问题场景

开发Android NFC读取功能时,onNewIntent方法已触发且日志正常输出,但通过intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)获取的Tag始终为空。使用NFC 213标签,已配置技术列表、Manifest权限等相关内容。

核心修复步骤

1. 修正PendingIntent的Flag配置

Android 12及以上版本对PendingIntent的可变性有严格限制,原代码中使用的FLAG_IMMUTABLE会阻止系统向Intent中注入Tag等动态Extra数据。需根据系统版本调整Flag:

val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
    PendingIntent.FLAG_UPDATE_CURRENT
}
pendingIntent = PendingIntent.getActivity(this, 0, intent, flags)

FLAG_UPDATE_CURRENT确保系统更新Intent的Extra数据,FLAG_MUTABLE(Android 12+)允许Intent内容被修改。

2. 明确指定支持的技术列表

NFC 213标签属于ISO 14443 Type A标准,需在enableForegroundDispatch中传入对应技术列表,确保系统正确识别并传递Tag:

// 构造支持的技术列表
val techListsArray = arrayOf(
    arrayOf(NfcA::class.java.name),
    arrayOf(Ndef::class.java.name),
    arrayOf(NdefFormatable::class.java.name)
)

// 启用前台调度时传入技术列表
nfcAdapter?.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)

3. 调整IntentFilter顺序与优先级

保持IntentFilter的合理顺序,让ACTION_TAG_DISCOVERED作为兜底(匹配所有NFC标签),避免因NDEF数据缺失导致的Tag传递失败:

val ndefIntentFilter = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
    try {
        addDataType("*/*")
    } catch (e: IntentFilter.MalformedMimeTypeException) {
        throw RuntimeException("Failed to add data type", e)
    }
}
val techIntentFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
val tagIntentFilter = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
intentFiltersArray = arrayOf(ndefIntentFilter, techIntentFilter, tagIntentFilter)

4. 排查Manifest配置冲突

确保Manifest中未注册与NFC相关的全局intent-filter,避免与前台调度的Intent处理逻辑冲突。同时确认必备权限已添加:

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />

修改后的完整关键代码示例

class MainActivity : AppCompatActivity() {

    private val TAG = "NFC_DEBUG"
    private var nfcAdapter: NfcAdapter? = null
    private var pendingIntent: PendingIntent? = null
    private var intentFiltersArray: Array<IntentFilter>? = null
    private var techListsArray: Array<Array<String>>? = null

    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView = findViewById(R.id.textView)
        setupNFC()
    }

    private fun setupNFC() {
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        nfcAdapter ?: run {
            Log.d(TAG, "NFC not available on this device")
            return
        }
        Log.d(TAG, "NFC adapter initialized")

        if (nfcAdapter!!.isEnabled) {
            Log.d(TAG, "NFC is enabled.")
        } else {
            Log.d(TAG, "NFC is supported but not enabled.")
        }

        val intent = Intent(this, javaClass).apply {
            addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
        }

        // 修正PendingIntent Flag
        val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        } else {
            PendingIntent.FLAG_UPDATE_CURRENT
        }
        pendingIntent = PendingIntent.getActivity(this, 0, intent, flags)

        // 调整IntentFilter顺序
        val ndefIntentFilter = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
            try {
                addDataType("*/*")
            } catch (e: IntentFilter.MalformedMimeTypeException) {
                throw RuntimeException("Failed to add data type", e)
            }
        }
        val techIntentFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
        val tagIntentFilter = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
        intentFiltersArray = arrayOf(ndefIntentFilter, techIntentFilter, tagIntentFilter)

        // 指定支持的技术列表
        techListsArray = arrayOf(
            arrayOf(NfcA::class.java.name),
            arrayOf(Ndef::class.java.name),
            arrayOf(NdefFormatable::class.java.name)
        )

        Log.d(TAG, "NFC setup complete")
    }

    override fun onResume() {
        super.onResume()
        nfcAdapter?.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
        Log.d(TAG, "Foreground dispatch enabled")
    }

    override fun onPause() {
        super.onPause()
        nfcAdapter?.disableForegroundDispatch(this)
        Log.d(TAG, "Foreground dispatch disabled")
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        Log.d(TAG, "On new intent called, action: ${intent.action}")
        textView.text = "NFC"
        val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
        if (tag != null) {
            Log.d(TAG, "TAG IS NOT NULL");
            val techList = tag.techList
            techList.forEach { tech -> Log.d(TAG, "Tech: $tech") }
        } else {
            Log.d(TAG, "TAG IS NULL, intent extras: ${intent.extras}")
        }
    }
}

内容的提问来源于stack exchange,提问作者LMB

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:30:40