如何通过NFC向电子纸NFC模块传输图片?Kotlin开发求助
问题分析与解决方案
核心误区:混淆Android Beam与NFC标签读写
你使用的setNdefPushMessage和setBeamPushUris是Android Beam对等传输API,仅用于两个支持Beam的Android设备间传输数据。而你对接的Good Display电子纸NFC模块,大概率是被动式NFC标签(仅存储数据,由主动设备读写),因此这两种方法完全不适用,这是失败的核心原因。
正确实现步骤:NFC标签写入NDEF数据
1. 配置权限与Manifest
在AndroidManifest.xml中添加NFC权限及相关配置:
<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <activity ...> <!-- 过滤NFC标签发现的Intent --> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <data android:mimeType="image/jpeg" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <!-- 指定支持的NFC技术类型 --> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity>
创建res/xml/nfc_tech_filter.xml定义支持的标签技术:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> </resources>
2. 实现标签检测与写入逻辑
替换原有点击事件,改为监听NFC标签发现事件并写入图片数据:
private var nfcAdapter: NfcAdapter? = null private var pendingIntent: PendingIntent? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) nfcAdapter = NfcAdapter.getDefaultAdapter(this) pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE ) sendButton = findViewById(R.id.btn_sendImage) sendButton.setOnClickListener { if (nfcAdapter?.isEnabled == false) { openNfcSettings() } else { Toast.makeText(this, "请将手机靠近NFC模块", Toast.LENGTH_SHORT).show() } } } override fun onResume() { super.onResume() nfcAdapter?.enableForegroundDispatch(this, pendingIntent, null, null) } override fun onPause() { super.onPause() nfcAdapter?.disableForegroundDispatch(this) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent?.let { handleNfcIntent(it) } } private fun handleNfcIntent(intent: Intent) { val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return val imageByteArray = // 替换为你的图片ByteArray(需压缩到标签容量范围内) val ndefMessage = createNdefMessage(imageByteArray) // 尝试写入NDEF数据 try { val ndef = Ndef.get(tag) if (ndef != null) { ndef.connect() if (!ndef.isWritable) { Toast.makeText(this, "标签不可写", Toast.LENGTH_SHORT).show() ndef.close() return } if (ndef.maxSize < ndefMessage.toByteArray().size) { Toast.makeText(this, "图片过大,超过标签容量", Toast.LENGTH_SHORT).show() ndef.close() return } ndef.writeNdefMessage(ndefMessage) Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show() ndef.close() } else { // 标签未格式化,尝试格式化并写入 val ndefFormatable = NdefFormatable.get(tag) ndefFormatable?.let { it.connect() it.format(ndefMessage) Toast.makeText(this, "格式化并写入成功", Toast.LENGTH_SHORT).show() it.close() } ?: run { Toast.makeText(this, "不支持NDEF格式的标签", Toast.LENGTH_SHORT).show() } } } catch (e: Exception) { Toast.makeText(this, "写入失败:${e.message}", Toast.LENGTH_SHORT).show() } } private fun createNdefMessage(image: ByteArray): NdefMessage { val mimeRecord = NdefRecord.createMime("image/jpeg", image) return NdefMessage(mimeRecord) } private fun openNfcSettings() { startActivity(Intent(Settings.ACTION_NFC_SETTINGS)) }
关键注意事项
- 图片大小限制:NFC标签容量通常极小(如NTAG213仅144字节,NTAG216为888字节),需将图片压缩到极小尺寸(比如128x128像素以下的JPEG),否则会超出容量。
- 标签兼容性:确认你的NFC模块支持NDEF格式,若仅支持原始数据写入,需使用
NfcA/NfcB等原始技术类发送APDU指令,需参考模块官方文档获取通信协议。 - 版本适配:Android 12+需使用
PendingIntent.FLAG_MUTABLE,注意权限与Intent配置的兼容性。
内容的提问来源于stack exchange,提问作者SatanasHammer
相关产品推荐
相关产品推荐

