Cannot detect an NfcV tag while other Android apps can
nicolascrochet7 opened this issue · 2 comments
Hi,
I am getting a weird behavior with this library.
I am using a tag that is configurable em4425 tag.
Before being configured I can easily detect and scan the tag and interact with it. Then I activate a feature on the tag and I am not getting any response from the app nor in the log ; while I can with any other NFC tool existing on Android and the tag still appears as a Iso15693 tag.
I would like to dig into what is going on, but I am not sure where I should start. How could I access deeper logs from the library to see what is making the library not detect the tag in the first place ?
Any advice appreciated :)
/// ISO 15693 NFC client.
class Iso15693NfcClient implements Iso15693NfcClientInterface {
Completer _completer = Completer();
Iso15693TagInstance? _iso15693tagInstance;
@override
Future<bool> get isNfcAvailable async =>
await NfcManager.instance.isAvailable();
@override
Future<Iso15693NfcUid> get uid async => await poll(() async {});
@override
Future<Iso15693NfcUid> poll(sequence, {Iso15693NfcUid? uid}) async {
// Check platform
if (env.platform != Platform.android && env.platform != Platform.iOS) {
throw const NfcUnavailableReaderException(
message: 'Platform has to be mobile to poll');
}
// Check Nfc availability
if (await isNfcAvailable == false) {
throw const NfcUnavailableReaderException(
message: 'Nfc reader unavailable, check permissions');
}
// Init completer session.
_completer = Completer();
// Listen for an ISO 15693 NFC tag.
await NfcManager.instance.startSession(
pollingOptions: {NfcPollingOption.iso15693},
onDiscovered: (tag) async {
log('NFC')
.fine("NFC tag discovered : ${tag.data.values.toString()}");
// Check tag validity
_iso15693tagInstance = Iso15693TagInstance(tag: tag);
final discoveredUid =
Iso15693NfcUid.fromUint8List(_iso15693tagInstance!.uid);
// Compare to uid
if (uid != null && discoveredUid != uid) {
throw NfcInvalidUidException(
message:
'Tag discovered ${discoveredUid.uid.toHexString()} is not the exptected one ${uid.uid.toHexString()}');
}
// Init user sequence
await sequence()
.then((value) => _completer.complete(discoveredUid))
.catchError((error) async {
_completer.completeError(error);
throw NfcCommandFailureException(
message: 'Command failure with error $error');
});
},
onError: _onError);
// Return its uid.
return await _completer.future;
}
Future<void> _onError(NfcError error) async {
log('NFC').severe('NFC error on session : ${error.message}');
_completer.completeError(error);
}
@override
Future<Iso15693NfcResponse> transceiveCommand(
Iso15693NfcCommand command) async {
log('NFC').fine("${command.commandName} : ${command.fullBytes.toHexString()}");
if (_iso15693tagInstance != null) {
final fullBytes = await _iso15693tagInstance!.transceiveCommand(command);
log('NFC').fine("Response : ${fullBytes.toHexString()}");
return Iso15693NfcResponse(fullBytes: fullBytes);
} else {
throw const NfcCommandFailureException(message: 'No tag discovered');
}
}
Future<void> stopPolling() async {
log('NFC').fine("NFC session stoped");
await NfcManager.instance.stopSession();
_iso15693tagInstance = null;
}
}
/// Generic NFC Manager library tag instance to transceive command
/// the same way between Android and iOS.
class Iso15693TagInstance {
final NfcTag tag;
// Provision android or iOS tag instance.
Iso15693TagInstance({required this.tag}) {
androidTag = NfcV.from(tag);
iOStag = Iso15693.from(tag);
if (androidTag == null && iOStag == null) {
throw const NfcInvalidUidException(
message: 'Discovered tag is not an ISO15693 tag.');
}
}
late final NfcV? androidTag;
late final Iso15693? iOStag;
/// Transceives command to Android or iOS tag instance depending on platform.
Future<Uint8List> transceiveCommand(Iso15693NfcCommand command) async {
if (env.platform == Platform.android) {
return await androidTag!.transceive(data: command.fullBytes);
} else if (env.platform == Platform.iOS) {
return await iOStag!.customCommand(
requestFlags: command.flags.toIso15693RequestFlags(),
customCommandCode: command.commandOpcode[0],
customRequestParameters: command.parameters);
} else {
throw const NfcUnavailableReaderException(
message:
'NFC is unavailable for platform other than Android and iOS');
}
}
/// Returns uid depending on Android and iOS.
///
/// Android returns uid in LSB-MSB while iOS MSB-LSB.
Uint8List get uid {
if (env.platform == Platform.android) {
return androidTag!.identifier.toReversed();
} else if (env.platform == Platform.iOS) {
return iOStag!.identifier;
} else {
throw const NfcUnavailableReaderException(
message:
'NFC is unavailable for platform other than Android and iOS');
}
}
}
Looking at my code, I see that I thought I had removed the polling option but in fact not. It works without it. Which is still weird.
@nicolascrochet7 Could you please suggest a convenient way to contact you regarding EM4425 tags? Thank you!