小米设备NFC调用nfcV.transceive()超13字节报Tag Was Lost问题求助
问题描述
开发一款搭载NFC功能的应用,使用ST25标签。当通过nfcV.transceive()命令发送超过13字节的数据时,小米智能手机会触发“TAG WAS LOST”错误,其他设备可正常运行。错误触发条件为messageBytes.size大于13字节。
相关代码
private fun readTag(intent: Intent) { if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action || NfcAdapter.ACTION_TECH_DISCOVERED == intent.action || NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) { val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG, Tag::class.java) if (tag != null) { val st25 = ST25DVTag.get(tag) st25?.connect() val stringToConvert = etDataToWrite.text.toString() val messageBytes = stringToConvert.toByteArray(Charset.forName("UTF-8")) try { st25.WriteMB(messageBytes.size - 1, messageBytes) } catch (e: IOException) { e.printStackTrace() Toast.makeText(this, "ERROR Write tag NFC: $e",Toast.LENGTH_SHORT).show() Log.e("NFC ERROR","OK write tag NFC: $e") } finally { try { st25.close() } catch (e: IOException) { e.printStackTrace() } } } fun WriteMB(size: Int , data:ByteArray): ByteArray { val writecommandLength = 4 + data.size // Calculate total length including data val writecommand = ByteArray(writecommandLength) // Copy ST25DV_REQUEST_HEADER, 0xCA, IC_MFG_CODE, and size System.arraycopy(byteArrayOf(ST25DV_REQUEST_HEADER,0xAA.toByte(),IC_MFG_CODE,size.toByte()),0, writecommand, 0, 4) // Copy the data to the end of writecommand System.arraycopy(data, 0, writecommand, 4, data.size) var lenmax = tag.maxTransceiveLength return safeTransceive(writecommand) } private fun safeTransceive(command: ByteArray): ByteArray { var nTry = 0 var errorCode = COMMAND_OK do { val response = tag.transceive(command) errorCode = response[0] Log.d("Transceive","ErrorCode:"+errorCode) if (errorCode == COMMAND_OK) return response.copyOfRange(1,response.size) else { nTry++ Thread.sleep(COMMAND_DELAY) } } while (nTry < COMMAND_RETRY) throw ST25DVException("IOError: code " + errorCode) }
解决方案
问题定位
这不一定是小米纯硬件问题,更可能是小米NFC驱动对NFC-V协议的收发长度限制或处理逻辑差异导致的。部分小米机型的NFC驱动在处理超过特定长度的NFC-V指令时,可能存在超时或帧处理错误,误报“TAG WAS LOST”。
具体解决办法
- 拆分数据分批写入:把超过13字节的数据拆分成多个小数据块,分多次调用写入接口。注意对应ST25标签的地址偏移,确保数据写入到正确的存储位置。
- 适配
maxTransceiveLength:代码中已获取tag.maxTransceiveLength但未实际利用,小米机型的该值可能更小。需要根据这个值动态调整单次发送的指令长度,避免超出设备支持的最大收发字节数。示例逻辑:val maxDataLen = tag.maxTransceiveLength - 4 // 减去指令头的4字节 if (data.size > maxDataLen) { // 实现数据拆分、分批写入逻辑 } else { // 直接执行原写入逻辑 } - 调整超时与重试策略:在
safeTransceive中延长指令间隔时间(Thread.sleep的时长),给小米设备足够的处理时间;同时可以尝试增大重试次数,提升长指令的成功率。 - 使用ST官方SDK方法:优先使用ST官方提供的ST25DV SDK封装的写入接口,这些方法通常已适配不同机型的兼容性问题,比自定义指令更稳定。
内容的提问来源于stack exchange,提问作者AndersonFw
相关产品推荐
相关产品推荐

