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

Android NFC开发报错:Unresolved reference: setNdefPushMessage

问题解答

1. setNdefPushMessage方法的状态

setNdefPushMessage和setNdefPushMessageCallback确实已被移除:

  • 这两个方法从Android 10(API 29)开始被标记为弃用
  • Android 11(API 30)正式移除了这些方法,同时Android Beam功能也被彻底移除,这是官方的平台变更,和Android Studio无关。

2. NFC文本传输的替代方案

由于Android Beam被移除,现在需要通过NFC Peer-to-Peer (P2P) 配合NDEF消息读写实现设备间文本传输,核心思路是将其中一台设备模拟为NFC标签,另一台设备写入/读取NDEF消息。以下是完整实现步骤:

前置准备

在AndroidManifest.xml中添加NFC权限和特性声明:

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

同时为接收消息的Activity添加NDEF_DISCOVERED意图过滤器:

<activity android:name=".MainActivity">
    <!-- 原有启动意图过滤器 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <!-- NFC NDEF消息监听 -->
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

发送端实现(写入NDEF消息)

import android.nfc.NfcAdapter
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import android.app.PendingIntent

class SenderActivity : AppCompatActivity() {
    private var nfcAdapter: NfcAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sender)
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
    }

    override fun onResume() {
        super.onResume()
        // 启用前台调度,优先捕获NFC事件
        nfcAdapter?.enableForegroundDispatch(
            this,
            PendingIntent.getActivity(
                this, 0,
                Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
                PendingIntent.FLAG_MUTABLE
            ),
            null,
            null
        )
    }

    override fun onPause() {
        super.onPause()
        nfcAdapter?.disableForegroundDispatch(this)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        val tag = intent?.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return
        // 创建要发送的文本NDEF消息
        val textRecord = NdefRecord.createTextRecord("en", "这是要发送的NFC文本")
        val message = NdefMessage(arrayOf(textRecord))
        // 写入消息到目标设备
        writeNdefMessage(tag, message)
    }

    private fun writeNdefMessage(tag: Tag, message: NdefMessage) {
        return try {
            val ndef = Ndef.get(tag)
            ndef.connect()
            if (!ndef.isWritable) {
                Toast.makeText(this, "目标设备不可写入", Toast.LENGTH_SHORT).show()
                ndef.close()
                return
            }
            if (ndef.maxSize < message.toByteArray().size) {
                Toast.makeText(this, "消息长度超过设备限制", Toast.LENGTH_SHORT).show()
                ndef.close()
                return
            }
            ndef.writeNdefMessage(message)
            Toast.makeText(this, "发送成功", Toast.LENGTH_SHORT).show()
            ndef.close()
        } catch (e: Exception) {
            e.printStackTrace()
            Toast.makeText(this, "发送失败", Toast.LENGTH_SHORT).show()
        }
    }
}

接收端实现(读取NDEF消息)

import android.nfc.NfcAdapter
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import android.app.PendingIntent
import java.nio.charset.Charset

class ReceiverActivity : AppCompatActivity() {
    private var nfcAdapter: NfcAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_receiver)
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
    }

    override fun onResume() {
        super.onResume()
        nfcAdapter?.enableForegroundDispatch(
            this,
            PendingIntent.getActivity(
                this, 0,
                Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
                PendingIntent.FLAG_MUTABLE
            ),
            null,
            null
        )
    }

    override fun onPause() {
        super.onPause()
        nfcAdapter?.disableForegroundDispatch(this)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent?.action) {
            val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
            rawMessages?.getOrNull(0)?.let { msg ->
                val ndefMessage = msg as NdefMessage
                val record = ndefMessage.records.firstOrNull() ?: return@let
                // 解析文本记录
                val text = parseNdefTextRecord(record)
                Toast.makeText(this, "收到消息:$text", Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun parseNdefTextRecord(record: NdefRecord): String {
        val payload = record.payload
        // 第一个字节的bit7表示编码,bit0-5表示语言码长度
        val isUtf16 = (payload[0].toInt() and 0x80) != 0
        val charset = if (isUtf16) Charset.forName("UTF-16") else Charset.forName("UTF-8")
        val languageCodeLength = payload[0].toInt() and 0x3F
        // 跳过语言码,读取文本内容
        return String(payload, languageCodeLength + 1, payload.size - languageCodeLength - 1, charset)
    }
}

注意事项

  • 两台设备都需要开启NFC功能
  • 传输时需将设备的NFC感应区域靠近
  • 部分设备可能需要在系统设置中开启"NFC读写"相关权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:07:09