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

