I'm developing a NFC environment consisting of a tag (AS3953 chip + microcontroller) and a smartphone (Samsung Galaxy Fame runnung Android 4.1.2).
While reading a NDEF message works I'm stuck on writing the message to the tag. 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(). Since all of them are listed the app continues to 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:
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. Looking further into the android code writeNdefMessage() tries to get a TagService and a ServiceHandle from the tag to match them against. 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.
Edit 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!
I configured AS3953 to ISO14443A Level-4 so only Tag Type 4 Blocks are forwarded to the microcontroller. 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. As I said reading the ndef file works and I tested it for a 4KB file. Looking at the logic analysis the following steps are made (all returning a positive 9000-code):
(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. Just as in the linked example the phone touches the tag calling onResume() doing mNfcAdapter.enableForegroundDispatch(...);
When I log the SPI communication the same reading procedure as above is done. 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.
Edit 2:
There might be a hint as one of the first interrupts issue a deselect command which is handled by AS3953 itself:
(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
Ndef
tag technology. – Azucenaazurec: 0x 00 b0 xx xx xx
) sent from the Android device to the AS3953? – AzucenaazureNdef.connect()
, Android disconnects the tag, tries to activate it again and selects the NDEF application. It should then read the CC file (and possible some bytes of the NDEF file) and check if the new NDEF message is smaller than the maximum size of the NDEF file. – Azucenaazure