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

Android应用开发中不使用intent能否点击按钮触发读取NFC卡片标签?

Kotlin Android 点击按钮触发NFC读取实现方案

1. 基础配置

首先在AndroidManifest.xml中添加NFC相关权限和特性声明,不需要配置NFC intent过滤器(避免系统自动唤起应用):

<!-- NFC权限 -->
<uses-permission android:name="android.permission.NFC" />
<!-- 声明应用需要NFC硬件,required设为false表示不强制要求设备支持NFC -->
<uses-feature android:name="android.hardware.nfc" android:required="false" />

2. 核心逻辑实现

核心思路是通过开关变量控制NFC读取时机,标签靠近时先暂存Intent不处理,只有用户点击按钮后再执行读取操作:

2.1 变量初始化

在Activity中定义所需变量:

private var nfcAdapter: NfcAdapter? = null
// NFC读取开关,默认关闭
private var isReadEnabled = false
// 暂存未处理的NFC Intent
private var pendingNfcIntent: Intent? = null
// 前台调度PendingIntent,用于当前应用接管所有NFC事件
private val nfcPendingIntent: PendingIntent by lazy {
    PendingIntent.getActivity(
        this,
        0,
        Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
}

2.2 生命周期与按钮事件处理

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_nfc_read)

    // 初始化NFC适配器
    nfcAdapter = NfcAdapter.getDefaultAdapter(this)
    if (nfcAdapter == null) {
        // 设备不支持NFC,提示用户
        Toast.makeText(this, "当前设备不支持NFC", Toast.LENGTH_SHORT).show()
        return
    }
    if (nfcAdapter?.isEnabled == false) {
        // NFC未开启,引导用户开启
        Toast.makeText(this, "请先开启NFC功能", Toast.LENGTH_SHORT).show()
        startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
    }

    // 读取按钮点击事件
    btnReadNfc.setOnClickListener {
        isReadEnabled = true
        // 如果已有暂存的NFC Intent,直接处理
        pendingNfcIntent?.let { intent ->
            processNfcIntent(intent)
            // 处理完重置状态
            pendingNfcIntent = null
            isReadEnabled = false
        } ?: run {
            Toast.makeText(this, "请将NFC标签靠近设备", Toast.LENGTH_SHORT).show()
        }
    }
}

override fun onResume() {
    super.onResume()
    // 前台时启用NFC前台调度,接管所有NFC事件
    nfcAdapter?.enableForegroundDispatch(this, nfcPendingIntent, null, null)
}

override fun onPause() {
    super.onPause()
    // 后台时禁用前台调度
    nfcAdapter?.disableForegroundDispatch(this)
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    // 过滤NFC相关Intent
    if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action
        || NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action
        || NfcAdapter.ACTION_TECH_DISCOVERED == intent.action) {
        if (isReadEnabled) {
            // 读取开关已开启,直接处理
            processNfcIntent(intent)
            isReadEnabled = false
        } else {
            // 读取开关未开启,暂存Intent
            pendingNfcIntent = intent
        }
    }
}

2.3 读取NFC标签内容实现

private fun processNfcIntent(intent: Intent) {
    val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return
    // 读取NDEF格式数据示例,可根据需求调整读取其他技术格式的标签
    val ndef = Ndef.get(tag)
    ndef?.use { ndefTag ->
        ndefTag.connect()
        val ndefMessage = ndefTag.ndefMessage
        val payload = ndefMessage.records[0].payload
        // 处理payload,转换为文本
        val text = String(payload, 3 until payload.size, Charset.forName("UTF-8"))
        runOnUiThread {
            Toast.makeText(this, "读取成功:$text", Toast.LENGTH_SHORT).show()
        }
    }
}

注意事项

  • 如果NFC标签一直保持靠近设备,系统仅会发送一次NFC Intent,暂存后点击按钮直接读取即可
  • 读取完成后及时重置isReadEnabled状态,避免后续标签靠近自动读取
  • 如果需要读取非NDEF格式的标签,可在processNfcIntent中替换为对应技术类的读取逻辑,比如MifareClassic、NfcA等

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:27:07