简体   繁体   English

Android NFC writeNdefMessage抛出IOException标签不是ndef

[英]Android NFC writeNdefMessage throws IOException Tag is not ndef

I'm developing a NFC environment consisting of a tag (AS3953 chip + microcontroller) and a smartphone (Samsung Galaxy Fame runnung Android 4.1.2). 我正在开发一个NFC环境,包括一个标签(AS3953芯片+微控制器)和一个智能手机(三星Galaxy Fame runnung Android 4.1.2)。

While reading a NDEF message works I'm stuck on writing the message to the tag. 在阅读NDEF消息时,我仍然坚持将消息写入标签。 I copied most of the code from http://tapintonfc.blogspot.de/2012/07/the-above-footage-from-our-nfc-workshop.html and modified it to accept ISO14443A Tag Type 4 by searching the tag techlist for IsoDep, NfcA and Ndef in supportedTechs(). 我从http://tapintonfc.blogspot.de/2012/07/the-above-footage-from-our-nfc-workshop.html复制了大部分代码,并通过搜索标签技术列表将其修改为接受ISO14443A标签类型4对于支持技术()中的IsoDep,NfcA和Ndef。 Since all of them are listed the app continues to writeTag(): 由于列出了所有这些,app继续writeTag():

public WriteResponse writeTag(NdefMessage message, Tag tag) {
try {
    Ndef ndef = Ndef.get(tag);
    if (ndef != null) {
        Log.d(TAG, "writeTag: tag type: "+ndef.getType());
        ndef.connect();
        Log.d(TAG, "writeTag: connected!");
        if (!ndef.isWritable()) {
            return new WriteResponse(0, "Tag is read-only");
        }
        if (ndef.getMaxSize() < message.toByteArray().length) {
            return new WriteResponse(0, "size error");
        }
        Log.d(TAG, "writeTag: write ndef...");
        ndef.writeNdefMessage(message);
        Log.d(TAG, "writeTag: wrote ndef!");
        if (writeProtect)
            ndef.makeReadOnly();
        return new WriteResponse(1, "Wrote message to pre-formatted tag.");
    } else {
        Log.d(TAG, "writeTag: ndef==null!");
        return new WriteResponse(0, "writeTag: ndef==null!");
    }
} catch (Exception e) {
    Log.d(TAG, "writeTag: exception: " + e.toString());
    return new WriteResponse(0, "Failed to write tag");
}
}

LogCat shows: LogCat显示:

11:08:46.400: onNewIntent
11:08:46.400: supportedTechs: techlist: android.nfc.tech.IsoDep,android.nfc.tech.NfcA,android.nfc.tech.Ndef,
11:08:46.400: supportedTechs: tech is supported!
11:08:46.400: writeTag: tag type: org.nfcforum.ndef.type4
11:08:46.410: writeTag: connected!
11:08:46.410: writeTag: write ndef...
11:08:46.490: writeTag: exception: java.io.IOException: Tag is not ndef

As you can see an IOException is thrown saying the Tag is not ndef which contradicts the techlist. 正如您所看到的,抛出IOException,表示Tag不是ndef,与技术列表相矛盾。 Looking further into the android code writeNdefMessage() tries to get a TagService and a ServiceHandle from the tag to match them against. 进一步研究android代码,writeNdefMessage()尝试从标记中获取TagService和ServiceHandle以匹配它们。 This fails so the exception is thrown (no message written up to now): 这会失败,因此抛出异常(到目前为止没有写入消息):

public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
...
INfcTag tagService = mTag.getTagService();
...
int serviceHandle = mTag.getServiceHandle();
if (tagService.isNdef(serviceHandle)) {
    ...
}
else {
    throw new IOException("Tag is not ndef");
}
...
}

Is there a workaround for that or is it not possible at all with my kind of tag? 是否有解决方法或者根本不可能使用我的标签? As I'm also programming the tag the error might be on the other side, but it seems to be a Java problem. 因为我也在编写标记,错误可能在另一边,但它似乎是一个Java问题。


Edit 1: 编辑1:

I don't connect to any technology before so there shouldn't be any opened connection. 我以前没有连接任何技术,因此不应该打开任何连接。 If I open an connection before ndef.connect() there is IllegalStateException: Close other technology first! 如果我在ndef.connect()之前打开连接,则会出现IllegalStateException:首先关闭其他技术!

I configured AS3953 to ISO14443A Level-4 so only Tag Type 4 Blocks are forwarded to the microcontroller. 我将AS3953配置为ISO14443A Level-4,因此只有Tag Type 4 Block被转发到微控制器。 Only I-Blocks are handled but even if there are other commands the µC has to read it out over the SPI port which isn't the case by logic analysis. 只处理I-Block,但即使有其他命令,μC也必须通过SPI端口读取它,而逻辑分析并非如此。 As I said reading the ndef file works and I tested it for a 4KB file. 正如我所说,阅读ndef文件工作,我测试了4KB文件。 Looking at the logic analysis the following steps are made (all returning a positive 9000-code): 查看逻辑分析,执行以下步骤(所有返回正9000代码):

(c=command, r=response) (corrected due to renaming mistake)
select by name:
c: 02 00 a4 04 00 07 d2 76 00 00 85 01 01 00
r: 02 90 00
select by id - select cc file
c: 03 00 a4 00 0c 02 e1 03
r: 03 90 00
read 0x0f bytes of cc file
c: 02 00 b0 00 00 0f
r: 02 00 0f 20 00 3b 00 34 04 06 e1 04 0f ff 00 00 90 00
select by id - select ndef file
c: 03 00 a4 00 0c 02 e1 04
r: 03 90 00
read 0x02 bytes (first 2 bytes are apdu-size)
c: 02 00 b0 00 00 02
r: 02 0f d3 90 00
read 0x3b bytes (frame size) of first part of ndef file (external type, jpeg image as payload)
c: 03 00 b0 00 02 3b
r: 03 c4 0c 00 00 0f c1 64 65 2e 74 65 73 74 61 70 70 3a 61 01 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 60 00 60 00 00 ff db 00 43 00 49 32 36 40 36 2d 49 40 3b 40 52 4d 49 56 6d 90 00
[ndef file]
read 0x26 bytes of last part of ndef file
c: 03 00 b0 0f ae 27
r: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF D9 00 00 90 00

Using the same app for writing I start the activity which filters NfcAdapter.ACTION_TAG_DISCOVERED intents. 使用相同的应用程序进行编写我启动过滤NfcAdapter.ACTION_TAG_DISCOVERED意图的活动。 Just as in the linked example the phone touches the tag calling onResume() doing mNfcAdapter.enableForegroundDispatch(...); 就像在链接的例子中一样,手机接触调用onResume()的标签做mNfcAdapter.enableForegroundDispatch(...);

When I log the SPI communication the same reading procedure as above is done. 当我记录SPI通信时,完成与上述相同的读取过程。 Since LogCat shows a working intent dispatcher I guess the app stops at the IOException, closing the connection and immediately going over to read out as android found the tag again. 由于LogCat显示了一个工作意图调度程序,我猜应用程序停止在IOException,关闭连接并立即读取,因为android再次找到了标记。


Edit 2: 编辑2:

There might be a hint as one of the first interrupts issue a deselect command which is handled by AS3953 itself: 可能有一个提示,因为第一个中断之一发出一个由AS3953本身处理的取消选择命令:

(count * interrupt)
3 * power up 
1 * Wake-up IRQ at entry in ACTIVE(*) state 
1 * Deselect command
1 * Wake-up IRQ at entry in ACTIVE(*) state 
1 * IRQ due to start of receive

It works now. 它现在有效。 I figured out that a startup routine which checks and sets the configuration word was transmitted with a too high baud rate for the AS3953. 我发现检查和设置配置字的启动例程是以过高的波特率传输的,用于AS3953。 This worked for reading but something must have been mixed up for writing to the tag. 这适用于阅读,但必须混淆写入标签的东西。

I cannot tell for sure if this is the only reason why it didn't work. 我无法确定这是否是它无效的唯一原因。 There is also a problem with slow reading of the 32Byte FIFO as waterlevel interrupts are handled too late - I simply expected the problem to be on the android side since I couldn't find the write command in the logic analysis and the exception didn't describe the reason enough. 由于水位中断的处理太迟,因此32Byte FIFO的读取速度也很慢 - 我只是期望问题出在android端,因为我在逻辑分析中找不到写命令而异常没有足够描述原因。

Thanks a lot to Michael Roland for further debugging, I still don't unterstand why the tag is read at first if I want to write to it but well - there should be a workaround reading an empty ndef message so the writing process will be done quickly. 非常感谢Michael Roland进行进一步的调试,我仍然没有解释为什么首先读取标签,如果我想写它但是很好 - 应该有一个解决方法,读取空的ndef消息,这样写入过程就完成了很快。

For now I have to work on the firmware and cannot forecast any further problems but the actual issue (ndef.writeNdefMessage()) returns successfully. 目前我必须处理固件,无法预测任何进一步的问题,但实际问题(ndef.writeNdefMessage())成功返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM