WearOS下Kotlin开发Android应用无法读取NFC标签求助
WearOS NFC标签读取问题修复方案
核心问题分析
- 成员变量初始化错误:
onCreate中声明了局部变量nfcAdapter,覆盖了类成员变量,导致onResume中调用enableReaderMode时使用的是未初始化的null对象,触发UnsupportedOperationException。 - NFC资源未释放:
onPause中注释了disableReaderMode调用,导致NFC资源无法正常释放,可能引发后续异常。 - ReaderMode Flags缺失:未添加
FLAG_READER_SKIP_NDEF_CHECK,系统会优先拦截NDEF格式标签,导致应用无法接收。 - TECH_DISCOVERED配置不完整:缺少对应的NFC技术列表配置文件,无法匹配标签技术类型。
- 日志输出错误:
ReaderCallback中错误引用了ContentValues.TAG,且未处理tag为空的情况。
修复后的代码实现
1. MainActivity.kt
package com.example.myapplicationxx import android.app.Activity import android.content.ContentValues.TAG import android.content.Intent import android.nfc.NdefMessage import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Build import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.annotation.RequiresApi import com.example.myapplicationxx.databinding.ActivityMainBinding class MainActivity : Activity() { private lateinit var binding: ActivityMainBinding private var nfcAdapter: NfcAdapter? = null private val callback = @RequiresApi(Build.VERSION_CODES.KITKAT) object : NfcAdapter.ReaderCallback { override fun onTagDiscovered(tag: Tag?) { tag?.let { val tagId = it.id.joinToString(separator = ":") { byte -> "%02X".format(byte) } Log.d("NFC", "发现NFC标签,ID: $tagId") // 这里可添加标签读取逻辑,比如解析NDEF内容 } ?: run { Log.d("NFC", "检测到空标签对象") } } } @RequiresApi(Build.VERSION_CODES.KITKAT) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 修复:将NFC适配器实例赋值给成员变量 nfcAdapter = NfcAdapter.getDefaultAdapter(this) val isNfcSupported = nfcAdapter != null && nfcAdapter?.isEnabled == true if(isNfcSupported){ Toast.makeText(this,"NFC已支持并启用",Toast.LENGTH_LONG).show(); nfcAdapter?.enableReaderMode(this, callback, NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or NfcAdapter.FLAG_READER_NFC_BARCODE or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, // 跳过系统NDEF拦截 null) }else{ Toast.makeText(this,"NFC未支持或未启用",Toast.LENGTH_LONG).show(); } } @RequiresApi(Build.VERSION_CODES.KITKAT) override fun onResume() { super.onResume() try { val isNfcSupported = nfcAdapter != null && nfcAdapter?.isEnabled == true if (isNfcSupported){ nfcAdapter?.enableReaderMode(this, callback, NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or NfcAdapter.FLAG_READER_NFC_BARCODE or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null) } } catch (e: Exception) { Log.e(TAG, "启用NFC读取模式失败", e) } } @RequiresApi(Build.VERSION_CODES.KITKAT) override fun onPause() { super.onPause() // 修复:释放NFC资源 nfcAdapter?.disableReaderMode(this) } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) Toast.makeText(this , "收到NFC Intent", Toast.LENGTH_SHORT).show() when(intent.action) { NfcAdapter.ACTION_NDEF_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TAG_DISCOVERED -> { val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES) rawMessages?.let { val messages = it.map { msg -> msg as NdefMessage } messages.forEach { msg -> Log.d("NFC", "NDEF消息记录数: ${msg.records.size}") // 此处可添加NDEF内容解析逻辑 } } } } } }
2. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.NFC" /> <!-- ReaderMode要求最低API19,更新minSdkVersion --> <uses-sdk android:minSdkVersion="19"/> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-feature android:name="android.hardware.type.watch" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@android:style/Theme.DeviceDefault"> <uses-library android:name="com.google.android.wearable" android:required="true" /> <meta-data android:name="com.google.android.wearable.standalone" android:value="true" /> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <!-- 添加TECH_DISCOVERED对应的技术列表配置 --> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity> </application> </manifest>
3. 创建NFC技术列表配置文件
在res/xml目录下新建nfc_tech_filter.xml:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.NfcBarcode</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> </resources>
关键修复说明
- 确保成员变量
nfcAdapter被正确初始化,避免局部变量覆盖。 - 在
onPause中必须调用disableReaderMode,释放NFC硬件资源。 - 添加
FLAG_READER_SKIP_NDEF_CHECK,让应用优先接收NFC标签,绕过系统默认的NDEF处理逻辑。 - 完善
TECH_DISCOVERED的配置,通过技术列表文件匹配主流NFC标签类型。 - 增加空值判断,避免
tag为空时出现空指针异常。
内容的提问来源于stack exchange,提问作者Ahmed Kortas
相关产品推荐
相关产品推荐

