Запись данных в тег NFC, который не подходит - PullRequest
0 голосов
/ 20 декабря 2018

В настоящее время мое Android-приложение использует URL для электронной таблицы Google, вставляя ее из буфера обмена, считывая QR-код или считывая из NFC.У меня проблемы с записью в тег NFC, и я получаю эту ошибку:

[ОШИБКА: nfa_rw_act.cc (1571)] Невозможно записать NDEF.Тег maxsize = 137, размер записи запроса = 171

Я не могу записать в этот тег, потому что полезная нагрузка, которую я пытаюсь записать, больше, чем место для записи на нем.

Все, что я пытаюсь сделать, это записать URL-адрес, который я уже прочитал (из буфера обмена или QR), в тег NFC, а также добавить запись моего приложения, чтобы он запустил Play Store в мое приложение, если у пользователя нетон уже установлен.К сожалению, кажется, что это слишком много данных.Я думал о том, чтобы включить только значение spreadsheetID, но думаю, что в будущем это усложнит ситуацию, когда я неизбежно захочу добавить поддержку электронных таблиц вне Google Sheets.

Вот как я пишу это в настоящее время:

public NdefMessage createNdefMessage() {
    String text = "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit?usp=sharing";

    NdefRecord appRecord = NdefRecord.createApplicationRecord(context.getPackageName());
    NdefRecord relayRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, new String("application/" + context.getPackageName()).getBytes(Charset.forName("US-ASCII")), null, text.getBytes());

    return new NdefMessage(new NdefRecord[] {relayRecord, appRecord});
}

Запись только идентификатора (в данном случае "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms") является единственным вариантом?Я также предполагаю, что тег NFC, который я использую, имеет средний размер, а не очень маленький для 2018 года.

РЕДАКТИРОВАТЬ:

Благодаря Майклу я смог привести его в соответствиеправда, едва (134/137 байт).Я пишу URI в NFC через это:

NdefRecord relayRecord = NdefRecord.createUri(text);

Я добавил этот фильтр намерений, чтобы поймать его:

<intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="https" android:host="docs.google.com"/>
        </intent-filter>

И я прочитал тег NFC с этим:

NdefMessage[] messages = new NdefMessage[rawMessages.length];

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

        for (NdefRecord r : messages[0].getRecords()) {
            if (r.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
                byte[] payload = r.getPayload();
                try {
                    String payloadText = new String(payload, 1, payload.length - 1, "UTF-8");
                    int firstByte = payload[0];
                    return getUriPrefix(firstByte) + payloadText;
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    return "Read error";
                }
            }
        }

И первый байт от сжатия URI, который я получаю через это, хотя я всегда назначаю «04» (4, когда я читаю его как int) в моем приложении:

private String getUriPrefix(int firstByte) {
    if (firstByte == 0) {
        return "";
    } else if (firstByte == 1) {
        return "http://www.";
    } else if (firstByte == 2) {
        return "https://www.";
    } else if (firstByte == 3) {
        return "http://";
    } else if (firstByte == 4) {
        return "https://";
    } else {
        return "";
    }
}

1 Ответ

0 голосов
/ 20 декабря 2018

Сообщение об ошибке, которое вы получили в журнале, довольно ясно.Ваше сообщение NDEF слишком велико для области данных тега.Очевидным решением будет использование тегов NFC с достаточно большой емкостью хранения - доступно довольно много больших тегов.Вы ничего не можете с этим поделать, если хотите сохранить именно это сообщение NDEF.

Однако есть способы улучшить само сообщение NDEF.В настоящее время вы используете запись MIME-типа для хранения URL.Это определенно не лучший выбор типа записи для хранения URL.(или фактически любые данные для конкретного приложения).Тип MIME, который вы выбрали, стоит ("application /" + context.getPackageName ()). Length () = 31 байт (при условии, что имя вашего пакета составляет 19 байт).

  • Если вывместо этого использовалась запись внешнего типа NFC Forum, вы могли бы создать гораздо более короткое имя типа в форме "mydomain.tld: appurl", так что это сэкономило бы немало байтов.

    relayRecord = NdefRecord.createExternal("mydomain.tld", "appurl", text.getBytes());
    
  • Поскольку вы хотите сохранить URL-адрес, существует даже более эффективный (и легко доступный) тип записи: общеизвестный тип URI Forum NFC.Имя типа этой записи состоит только из одной буквы «U», поэтому это позволит сэкономить 30 байтов по сравнению с вашей записью MIME-типа.Кроме того, тип записи URI использует схему сжатия для дальнейшего уменьшения размера записи: существует список хорошо известных префиксов URI (например, «https://"), который может быть представлен как один байт в записи URI (методNdefRecord.createUri() автоматически позаботится об этом сжатии.) Следовательно, вы сэкономите еще 7 байтов.

    relayRecord = NdefRecord.createUri(text);
    
...