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
相关产品推荐
相关产品推荐

