如何在Flutter构建的Android RFID标签模拟器中获取设备被读取的UID
可行实现方案说明
核心逻辑
Android设备在HCE(主机卡模拟)模式下被RFID阅读器读取时,会生成临时UID。要获取阅读器读到的同一UID,需在HCE服务的APDU交互流程中捕获当前会话的临时UID,再通过Flutter与原生的通信机制传递到Flutter层,最终和阅读器上传的UID完成后端交叉校验。
具体实现步骤
1. 编写Android原生HCE服务
Flutter无法直接处理底层NFC的APDU交互,需通过Android原生代码实现:
- 创建继承自
HostApduService的服务类,重写processCommandApdu()方法处理阅读器发送的指令。 - 当阅读器发起UID读取请求时,系统会触发该方法,此时可从会话上下文的Tag对象中提取当前临时UID。
2. 捕获UID的原生代码示例(Kotlin)
class HceService : HostApduService() { private val methodChannel = MethodChannel(this, "nfc_hce_channel") override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray { // 获取当前会话的Tag对象,提取UID字节数组 val tag = extras?.getParcelable<Tag>(EXTRA_TAG) tag?.id?.let { uidBytes -> // 转为阅读器一致的十六进制字符串格式 val uid = uidBytes.joinToString("") { "%02X".format(it) } // 将UID传递给Flutter层 methodChannel.invokeMethod("onUidCaptured", uid) } // 返回符合规范的APDU响应,保证阅读器会话正常完成 return byteArrayOf(0x90.toByte(), 0x00.toByte()) } override fun onDeactivated(reason: Int) {} }
3. Flutter层接收并上传UID
通过MethodChannel监听原生传递的UID,再发送至后端:
final MethodChannel _nfcChannel = MethodChannel('nfc_hce_channel'); @override void initState() { super.initState(); _nfcChannel.setMethodCallHandler((call) async { if (call.method == 'onUidCaptured') { String capturedUid = call.arguments as String; // 调用接口将UID发送至后端 await _uploadUidToServer(capturedUid); } }); } Future<void> _uploadUidToServer(String uid) async { // 此处实现后端接口调用逻辑 }
4. 后端交叉校验规则
- 阅读器读取UID后立即上传至服务器
- 设备自身捕获UID后也上传至服务器
- 服务器在短时间窗口(如5秒)内匹配两个相同的UID,匹配成功则完成认证
关键注意事项
- 需在AndroidManifest中声明NFC权限及HCE服务,添加
<uses-permission android:name="android.permission.NFC"/>,并为HCE服务配置对应的intent-filter。 - 临时UID会随每次会话变化,但阅读器与设备捕获的是同一会话的UID,短时间窗口内的匹配逻辑是可靠的。
- 必须保证HCE服务正确响应阅读器的APDU指令,否则阅读器无法完成UID读取,设备也无法捕获到对应值。
内容的提问来源于stack exchange,提问作者Mohit Jain
相关产品推荐
相关产品推荐

