12

我刚开始使用 Android NFC 进行编码,我已经成功地将 NDEF 数据读写到 mifare 经典标签中。问题是当应用程序从 ndef 记录中读取有效负载时,它总是在文本的开头包含字符 '*en'。我认为这是语言字符,但是没有该字符如何获得真正的短信?

这是应用程序从标签中读取的屏幕截图,实际文本是“Hello World”

在此处输入图像描述 这是要阅读的代码

@Override
public void onNewIntent(Intent intent) {
    Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
   // mText.setText("Discovered tag NDEF " + ++mCount + " with intent: " + intent);

    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

        if (rawMsgs != null) {
            NdefMessage[] msgs = new NdefMessage[rawMsgs.length];

            for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }

            NdefMessage msg = msgs[0];

            try {
            mText.setText(new String(msg.getRecords()[0].getPayload(), "UTF-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
4

3 回答 3

16

您看到的是转换为 UTF8 的 NDef 文本记录的原始数据。

NDef 文本记录是这样构建的:

第一个字节:控制字节

位 7:0:文本以 UTF-8 编码 1:文本以 UTF16 编码

位 6:RFU(必须设置为零)

Bit 5..0:IANA 语言代码的长度。

后面是语言代码,存储在 RFC 3066 中定义的 US-ASCII(在您的情况下为 en)。语言代码的长度在控制字节中给出。

其后是控制字节第 7 位指定格式的文本。

空方字符来自您将原始数据转换为 UTF-8。我几乎可以肯定您的情况下的控制字节具有数值 2。由于该数值没有可打印的字符,因此它被 unicode 集中的不可打印占位符字符替换。这通常显示为一个空方块。

于 2011-10-27T16:11:46.187 回答
2

这是我在KotlinAPI 29上所做的:

// ... in the onIntent(...) method
val parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)

parcelables?.let {
    try {
        val inNdefMessage = parcelables[0] as NdefMessage
        val inNdefRecords = inNdefMessage.records

        // convert the payload to string and drop 3 characters to get
        // rid of the " en" prefix
        val payload = inNdefRecords[0].payload

        // figure out if we need to take out the " en" at the beginning
        val textEncoding = if(payload[0] and 128.toByte() == 0.toByte()) "UTF-8" else "UTF-16"
        val langCodeLength = payload[0] and 63.toByte()

        // create a string starting by skipping the first 3 characters
        // based on the language code length
        var inMessage = String(
            payload,
            langCodeLength + 1,
            payload.count() - langCodeLength - 1,
            charset(textEncoding))

        // try to convert the message to json
        try {
            val json = JsonParser().parse(inMessage)

            // ... use json or whatever here
        } catch (error: Exception) {
            println("NFC tag data seems to invalid:\n\n$inMessage\n\n${error.localizedMessage}")
        }

        // ... do whatever
    } catch (error: Exception) {
        println("Error attempting to pull tag info: ${error.localizedMessage}")
    }
}
于 2020-10-14T01:51:23.433 回答
0

这是我在与此类似的帖子上找到的答案。

读取 NFC 标签时,这将隔离消息并排除消息开头的语言代码。

            byte[] payloadBytes = ndefRecord.getPayload();
        boolean isUTF8 = (payloadBytes[0] & 0x080) == 0;  //status byte: bit 7 indicates encoding (0 = UTF-8, 1 = UTF-16)
        int languageLength = payloadBytes[0] & 0x03F;     //status byte: bits 5..0 indicate length of language code
        int textLength = payloadBytes.length - 1 - languageLength;
        String languageCode = new String(payloadBytes, 1, languageLength, "US-ASCII");
        String payloadText = new String(payloadBytes, 1 + languageLength, textLength, isUTF8 ? "UTF-8" : "UTF-16");

        edtUser.setText(payloadText);

读取 NFC 标签时出现奇怪的字符

于 2020-11-13T09:16:23.743 回答