【问题标题】:Android NFC: 'd' prepended on NDEF payloadAndroid NFC:在 NDEF 有效负载上附加“d”
【发布时间】:2016-07-01 14:43:59
【问题描述】:

我有一个应用程序可以读取 MIFARE Ultralight 标签上的 NDEF 记录的有效负载。

负载打包到 NDEF 文本记录中,文本值格式如下:

1,10,200,Arthur smith

所以总是有 3 个逗号将 3 个数字和名称分开。

我使用 NXP TagWriter 格式化标签,我的应用程序可以正确读取有效负载。问题是我工作的公司使用了一家单独的公司来为我们格式化标签。现在,当我的应用程序扫描这些标签时,出现了问题。有效载荷然后读取:

d1,10,200,Arthur smith

这会导致我的应用不处理标签。

NXP 应用程序可以成功读取标签,如果我使用 NXP TagWriter 用相同的数据重新格式化标签,那么我的应用程序将正确读取标签。

当来自格式化公司的有效载荷前似乎有一个“d”,只有我的应用程序可以看到。

有没有人知道“d”是什么以及如何解决这个问题?

这是我用来读取有效载荷的代码:

if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(i.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(i.getAction())) {
    if(NfcScannerApplication.isCanScanNfcTag() == true){
        messages = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (messages != null) {
            //setContentView(R.layout.successfulnfc);
            NfcScannerApplication.startNfcTimer();
            //Toast.makeText(this, "NFC timer set", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one
            vibrate(); // signal found messages :-)

            // parse to records
            for (int i = 0; i < messages.length; i++) {
                List<Record> records = null;
                try {
                    records = new Message((NdefMessage)messages[i]);
                } catch (FormatException e) {
                    e.printStackTrace();
                }
                Log.e(TAG, "Found " + records.size() + " records in message " + i);

                for(int k = 0; k < records.size(); k++) {
                    Log.e(TAG, " Record #" + k + " is of class " + records.get(k).getClass().getSimpleName());

                    Record record = records.get(k);
                    NdefRecord ndefRecord = record.getNdefRecord();
                    byte[] arr = ndefRecord.getPayload();

                    String payload = new String(arr);

                    if(payload.length() > 0){
                        payload = payload.substring(3, payload.length());

                        Log.e(TAG, "payload = " + payload);

                        int counter = 0;
                        for( int z = 0;  z < payload.length(); z++ ) {
                            if( payload.charAt(z) == ',' ) {
                                counter++;
                            }
                        }

                        if(counter == 3){
                            //Toast.makeText(this, "comma count = 3 ", Toast.LENGTH_SHORT).show();
                            String[] splitPayload = payload.split(",");
                            String tagType = splitPayload[0];
                            String tagCompany = splitPayload[1];
                            String tagClientID = splitPayload[2];
                            String tagClientName = splitPayload[3];

【问题讨论】:

  • 如何读取应用中的有效负载?您如何使用 NXP TagWriter 编写有效负载(即您选择了什么格式)?
  • 我对 NFC 标签格式化公司进行了一些研究,他们通过 NXP TagWriter 中的 .csv 文件将数据加载到标签上。如果他们手动将数据一个一个地写入标签,那么前面就没有'd'。从 excel 电子表格加载时似乎会出现“d”???
  • 我在使用 NXP tagwriter 时使用的格式是纯文本。关于我用来读取有效负载的代码,我可以向您发布我的源代码。 [EDIT1]

标签: android character-encoding format nfc ndef


【解决方案1】:

您的代码未正确解码 NDEF 文本记录的有效负载。您假设有效负载是 UTF-8 编码的(Android 上的默认编码),并且实际文本值从该解码字符串的偏移量 3 开始:

NdefRecord ndefRecord = record.getNdefRecord();
byte[] arr = ndefRecord.getPayload();
String payload = new String(arr);
payload = payload.substring(3, payload.length());

但是,这些假设是错误的。文本记录由一个状态字节、后跟一个可变长度的语言代码(US-ASCII 编码)和文本值本身(以 UTF-8 或 UTF-16 编码)组成。因此,您看到的附加“d”实际上可能是语言代码的一部分,或者可能是将不正确的字符代码(例如状态字节的值)解码为 UTF-8 字符串的结果。

因此,为了得到文本值,首先要从状态字节中找出语言代码的长度和文本值的编码:

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");

【讨论】:

    【解决方案2】:

    我的猜测是,格式化公司可能正在对他们创建的标签做一些事情,以确保您的公司不能轻易地从这些标签中切换出来。

    但是,我不明白为什么您不能只检查有效负载中的初始“d”,然后在找到时将其剥离。

    【讨论】:

    • K 嗨,是的,我只是想避免源代码更改,因为目前大约 4000 台设备上安装了我的应用程序,更新它在逻辑上是一场噩梦
    • 我认为最好趁现在还早。但是,如果您的应用扫描其他标签之一,它似乎已经不起作用,因此更新只会是有益的。
    【解决方案3】:

    事实证明,NXP TagWiter 应用程序中存在一个错误,该错误位于“d”前面。 我不得不等待 NXP 的更新来解决这个问题。

    感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多