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

Android写入Ntag系列标签后NFC数据格式不符问题咨询

问题分析与修复方案

你的核心问题出在NDEF URI记录的构造逻辑不符合NFC Forum标准,导致写入的数据无法被NfcTools正确识别。以下是具体问题和修复步骤:

1. 关键错误点拆解

(1) URI标识符字节非法

你代码中使用的0x55不是合法的NDEF URI标识符。NFC标准中,URI标识符是0x00~0x1F的字节,用于缩写常见的URI前缀(比如0x03代表http://,0x04代表https://),而0x55是ASCII字符'U',完全不符合规范。

(2) Payload长度计算错误

你用subsUri.length作为NDEF记录的长度字段,这是错误的。NDEF记录头中D1 01后的长度字段,应该是整个URI Payload的长度(1字节标识符 + 缩写后剩余URI的字节数),而非仅host的长度。

(3) URI未按标准缩写

直接将完整URI转成字节写入,没有利用NDEF URI的缩写规则,既浪费存储空间,也会导致记录结构不符合标准。

2. 修复后的代码

下面是严格遵循NDEF规范的修正版writePages方法:

fun writePages(msg: String, mifare: MifareUltralight) {
    val uri = Uri.parse(msg).normalizeScheme()
    val (uriCode, trimmedUri) = getUriCodeAndTrimmedUri(uri.toString())

    // 构造合法的NDEF URI记录
    val payloadLength = 1 + trimmedUri.length // 1字节标识符 + 剩余URI长度
    val ndefRecord = byteArrayOf(
        0xD1.toByte(), 0x01.toByte(), payloadLength.toByte(),
        uriCode.toByte()
    ) + trimmedUri.toByteArray(Charsets.US_ASCII)

    // 包装成NDEF Message TLV块:0x03(TLV标签) + 数据长度 + NDEF记录 + 0xFE(终止TLV)
    val tlvEncodedData = byteArrayOf(0x03.toByte(), ndefRecord.size.toByte()) + ndefRecord + byteArrayOf(0xFE.toByte())

    var currentPage = 4
    for (i in tlvEncodedData.indices step 4) {
        val endIndex = min(i + 4, tlvEncodedData.size)
        val data = tlvEncodedData.sliceArray(i until endIndex)
        
        // 构造写页命令:A2 [页地址] [4字节数据],不足补0
        val command = byteArrayOf(0xA2.toByte(), currentPage.toByte()) + data
        if (command.size < 6) {
            command += ByteArray(6 - command.size)
        }
        mifare.transceive(command)
        currentPage += 1
    }
}

// 匹配URI前缀,返回对应的标识符和裁剪后的URI
private fun getUriCodeAndTrimmedUri(uri: String): Pair<Int, String> {
    return when {
        uri.startsWith("http://www.") -> 0x01 to uri.substring(11)
        uri.startsWith("https://www.") -> 0x02 to uri.substring(12)
        uri.startsWith("http://") -> 0x03 to uri.substring(7)
        uri.startsWith("https://") -> 0x04 to uri.substring(8)
        uri.startsWith("tel:") -> 0x05 to uri.substring(4)
        uri.startsWith("mailto:") -> 0x06 to uri.substring(7)
        // 其他常见前缀可参考NFC Forum规范补充
        else -> 0x00 to uri // 0x00代表不使用缩写,完整写入URI
    }
}

3. 额外注意事项

  • 密码验证:如果Ntag启用了密码保护,写入前必须先执行密码验证命令:mifare.transceive(byteArrayOf(0x1B.toByte(), *passwordBytes)),否则写入操作会静默失败。
  • 字符编码:URI必须使用US-ASCII编码,避免非ASCII字符,否则部分设备无法识别。
  • 存储空间限制:不同型号Ntag的用户页容量不同(比如Ntag213有42个用户页),确保写入的TLV数据不超出设备容量。

4. 验证

修复后用NfcTools扫描标签,应该能正确识别URI记录,且未安装对应APP时会自动触发浏览器打开目标链接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:06:28