Android NDEF记录有效负载上的奇怪字符

时间:2011-10-27 14:36:34

标签: android nfc ndef

我刚刚开始使用Android NFC编码,我已成功读取和编写NIFF数据到mifare经典标签。问题是当app从ndef记录中读取有效负载时,它总是在文本的开头包含字符'* en'。我认为这是语言特征,但是如何在没有该角色的情况下获得真正的短信?

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

enter image description here 这是要阅读的代码

@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();
            }
        }
    }
}

3 个答案:

答案 0 :(得分:14)

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

NDef文本记录的构建如下:

第一个字节:Control-Byte

  

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

     

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

     

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

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

接下来是控制字节的第7位指定格式的文本。

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

答案 1 :(得分:0)

这就是我在 API 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}")
    }
}

答案 2 :(得分: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);

Strange character when reading NFC tag