Hello NXP team,
I'm currently working with NTAG213 PVC cards in a Flutter mobile application using the flutter_nfc_kit package, and I'm facing a consistent and puzzling issue:
Problem:
After using my application to secure the card, then trying to write on it using an external app, the first write attempt always fails.
However, the second attempt immediately afterward succeeds without issue.
Even more puzzling: the card remains readable, although my code should lock both read and write access.
Password Setup (from Backend):
The backend provides the following:
"pwd": [18, 52, 86, 120]
"pack": [18, 52]
In my code:
- I write PWD to page 0x2B
- I write PACK to page 0x2C
- I write AUTH0 + ACCESS to page 0x29 as [0x00, 0x80, 0x00, 0x00]
This should lock both read and write access from page 0 unless authenticated.
My Questions:
- Is this a known behavior on NTAG213 cards?
- Am I missing something in my configuration or command sequence?
My Full Flutter Code (Writing + Locking):
Future<void> startNFCScan() async {
_isProcessing.value = true;
try {
var availability = await FlutterNfcKit.nfcAvailability;
if (availability != NFCAvailability.available) {
CustomSnackBar.error('NFC Not Available');
_isProcessing.value = false;
return;
}
var tag = await FlutterNfcKit.poll(
iosMultipleTagMessage: "Multiple tags found!",
iosAlertMessage: "Scan your tag",
);
await _encodeCard(tag: tag);
} catch (error) {
CustomSnackBar.error(error.toString());
}
_isProcessing.value = false;
}
Future<void> _encodeCard({required NFCTag tag}) async {
List<ndef.NDEFRecord> records = await FlutterNfcKit.readNDEFRecords();
if (records.isNotEmpty && records[0].payload!.isNotEmpty) {
CustomSnackBar.error('NFC Tag already has been encoded');
await FlutterNfcKit.finish();
return;
}
try {
final model = EncodeCardRequestModel.fromTag(tag);
final response = await ApiServices.encodeCardApi(model);
if (response != null) {
EncodeCardResponseModel responseModel = response;
await _lockCard(responseModel);
CustomSnackBar.success('Card written successfully!');
}
} catch (e) {
log(e.toString());
CustomSnackBar.error('Failed to encode card');
} finally {
await FlutterNfcKit.finish();
}
}
Future<void> _lockCard(EncodeCardResponseModel responseModel) async {
final writeToCardValue = responseModel.data.writeToCard;
final List<int> pwd = responseModel.data.nfcSecurity.pwd;
final List<int> pack = responseModel.data.nfcSecurity.pack;
final dataBytes = base64Decode(writeToCardValue);
for (int i = 0; i < dataBytes.length; i += 4) {
final page = 4 + (i ~/ 4);
final block = dataBytes.sublist(
i,
(i + 4 > dataBytes.length) ? dataBytes.length : i + 4,
);
while (block.length < 4) {
block.add(0x00);
}
final cmd = [0xA2, page, ...block];
final uint8listCmd = Uint8List.fromList(cmd);
await FlutterNfcKit.transceive(uint8listCmd);
}
final transceivePWD = [0xA2, 0x2B, ...pwd];
final uint8listPwd = Uint8List.fromList(transceivePWD);
final pwdResponse = await FlutterNfcKit.transceive(uint8listPwd);
final transceivePack = [0xA2, 0x2C, ...pack, 0x00, 0x00];
final uint8listPack = Uint8List.fromList(transceivePack);
final packResponse = await FlutterNfcKit.transceive(uint8listPack);
final transceiveAuth = [0xA2, 0x29, 0x00, 0x80, 0x00, 0x00];
final uint8listAuth = Uint8List.fromList(transceiveAuth);
final authResponse = await FlutterNfcKit.transceive(uint8listAuth);
log(pwdResponse.toString());
log(packResponse.toString());
log(authResponse.toString());
}
Any advice or explanation will be greatly appreciated
Hello, I hope you are doing fine.
My apologies sir,
Unfortunately, the support for Flutter is out of my support scope. I'll be happy to help with any NTAG 213 functionality issue or the implementation of our software using our software.
We do have a Library called Taplinx , is for both Android and, iOS.
TapLinx does have a full API for our Tags interfacing with your smartphone.
I'm very sorry, I can only recommend please request support with the respective developer's sites of the API you are using.