目前,我的Android应用通过从剪贴板粘贴,读取QR码或从NFC中读取来使用Google电子表格的URL。我在写入NFC标签时遇到问题,出现此错误:
[错误:nfa_rw_act.cc(1571)]无法写入NDEF。标签maxsize = 137,请求写入大小= 171
我无法写入此标签,因为我要写入的有效载荷大于其上的可写空间。
我要做的就是将我已经阅读过的URL(从剪贴板或QR)写入NFC标签,并添加我的应用程序记录,以便在用户未登录时将Play商店启动到我的应用程序还没有安装。不幸的是,这似乎是太多数据。我考虑过可能只包括电子表格ID值,但是当我不可避免地想在Google表格之外添加对电子表格的支持时,这会增加将来的麻烦。
这是我目前的书写方式:
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});
}
仅写ID(在这种情况下为“ 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms”)是我唯一的选择吗?我还假设我正在使用的NFC标签是平均大小,而不是2018年的超小标签。
编辑:
多亏了Michael,我才能够适应它,尽管勉强(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";
}
}
}
即使我只在我的应用中分配了“ 04”(当我将其读取为int时为4),我仍然可以通过URI压缩获得第一个字节:
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 "";
}
}
答案 0 :(得分:1)
您在日志中收到的错误消息非常清楚。您的NDEF消息太大,无法容纳标签的数据区域。显而易见的解决方案是使用具有足够大存储容量的NFC标签-有很多较大的标签可用。如果您想完全存储NDEF消息,则无能为力。
但是,有一些方法可以改善NDEF消息本身。当前,您使用MIME类型记录来存储URL。绝对不是存储URL的记录类型的最佳选择。 (或者实际上是任何特定于应用程序的数据)。您选择的MIME类型需要花费(“ application /” + context.getPackageName())。length()= 31个字节(假设包名称为19个字节)。
如果您改用NFC论坛外部类型记录,则可以创建形式更短的类型名称,形式为“ mydomain.tld:appurl”,这样可以节省很多字节。
relayRecord = NdefRecord.createExternal("mydomain.tld", "appurl", text.getBytes());
由于要存储URL,因此还有一种更有效(且随时可用)的记录类型:NFC论坛URI众所周知的类型。该记录的类型名称仅包含单个字母“ U”,因此与您的MIME类型记录相比,这将节省30个字节。此外,URI记录类型使用压缩方案来进一步减小记录的大小:存在一系列众所周知的URI前缀(例如“ https://”),可以将其表示为URI记录中的单个字节(方法NdefRecord.createUri()
将自动处理该压缩)。因此,您将另外节省7个字节。
relayRecord = NdefRecord.createUri(text);