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

WearOS下Kotlin开发Android应用无法读取NFC标签求助

WearOS NFC标签读取问题修复方案

核心问题分析

  1. 成员变量初始化错误:onCreate中声明了局部变量nfcAdapter,覆盖了类成员变量,导致onResume中调用enableReaderMode时使用的是未初始化的null对象,触发UnsupportedOperationException。
  2. NFC资源未释放:onPause中注释了disableReaderMode调用,导致NFC资源无法正常释放,可能引发后续异常。
  3. ReaderMode Flags缺失:未添加FLAG_READER_SKIP_NDEF_CHECK,系统会优先拦截NDEF格式标签,导致应用无法接收。
  4. TECH_DISCOVERED配置不完整:缺少对应的NFC技术列表配置文件,无法匹配标签技术类型。
  5. 日志输出错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 00:00:02