I forked the plugin nativescript-nfc and implemented the NFC write feature for iOS, it works well when using NativeScript 6. But if I upgrade the plugin to 7 or 8, the writing doesn't work, NFCNDEFTag.prototype.queryNDEFStatusWithCompletionHandler
is always undefined.
The implementation of writing NFC is shown below.
readerSessionDidDetectTags(
session: NFCNDEFReaderSession,
tags: NSArray<NFCNDEFTag> | NFCNDEFTag[]
): void {
const tag = tags[0];
session.connectToTagCompletionHandler(tag, (error: NSError) => {
console.log("connectToTagCompletionHandler");
if (error) {
console.log(error);
session.invalidateSessionWithErrorMessage("Error connecting to tag.");
this.errorCallback(error);
return;
}
const ndefTag: NFCNDEFTag = new interop.Reference<NFCNDEFTag>(
interop.types.id,
tag
).value;
try {
NFCNDEFTag.prototype.queryNDEFStatusWithCompletionHandler.call(
ndefTag,
(status: NFCNDEFStatus, number: number, error: NSError) => {
console.log("queryNDEFStatusWithCompletionHandler");
if (status == NFCNDEFStatus.NotSupported) {
var errMessage = "Tag is not NDEF compliant.";
session.invalidateSessionWithErrorMessage(errMessage);
} else if (status === NFCNDEFStatus.ReadOnly) {
var errMessage = "Tag is read only.";
session.invalidateSessionWithErrorMessage(errMessage);
} else if (status === NFCNDEFStatus.ReadWrite) {
const ndefMessage = this._owner.get().message;
NFCNDEFTag.prototype.writeNDEFCompletionHandler.call(
ndefTag,
ndefMessage,
(error: NSError) => {
if (error) {
console.log(error);
session.invalidateSessionWithErrorMessage("Write failed.");
this.errorCallback(error);
} else {
if (
ndefMessage.records[0].typeNameFormat ==
NFCTypeNameFormat.Empty
) {
session.alertMessage = "Erased data from NFC tag.";
} else {
if (this.options.writeHint) {
session.alertMessage = this.options.writeHint;
}
this.resultCallback(NfcHelper.ndefToJson(ndefMessage));
}
session.invalidateSession();
}
}
);
}
}
);
} catch (e) {
session.alertMessage = "error";
}
});
}
I'm not sure if I implement it in the correct way for NativeScript 7 or 8, but at least it works on 6, I actually don't believe it's a bug in the NativeScript across both 7 and 8. We used to live with 6 for a long time just for using this plugin, but really need to upgrade to 7 or 8 for the sake of other features.
Any help, suggestion or comment would be highly appreciated!
Below is the repo and branches for different NativeScript versions.
Repo: https://github.com/nordsense/nativescript-nfc
Branch feature/upgrade-nativescript
: This is NativeScript 8, only read works
Branch nordsense
: This is NativeScript 6 and both read and write work
You can use the demo project to test, set ndef listener
is for read and write Text
is for write
I managed to get it working on NS 8. Referring to the below code snippet, if NFCNDEFTag.prototype
is accessed before line 2, like the code in line 1 or by using console.dir(NFCNDEFTag.prototype)
, line 3 will dump the correct data that belongs to the correct protocol NFCNDEFTag
, the remaining code also works well ; if commenting out line 1, line 3 will dump incorrect data which belongs to some other protocols/objects like NSKeyValueCoding
and UIAccessibilityAction
. I still don't know why this happens, feel like a NativeScript issue, I filed an issue here https://github.com/NativeScript/NativeScript/issues/9609
I rebuilt the plugin and published the package here https://github.com/cloudhx/nativescript-plugins
readerSessionDidDetectTags(session: NFCNDEFReaderSession, tags: NSArray<NFCNDEFTag> | NFCNDEFTag[]): void {
const prototype = NFCNDEFTag.prototype; // Line 1
const tag = (<NSArray<NFCNDEFTag>>tags).firstObject; // Line 2
console.dir(NFCNDEFTag.prototype); // Line 3
session.connectToTagCompletionHandler(tag, (error: NSError) => {
console.log('connectToTagCompletionHandler');
if (error) {
console.log(error);
session.invalidateSessionWithErrorMessage('Unable to connect to tag.');
this.errorCallback(error);
return;
}
const ndefTag: NFCNDEFTag = new interop.Reference<NFCNDEFTag>(interop.types.id, tag).value;
try {
NFCNDEFTag.prototype.queryNDEFStatusWithCompletionHandler.call(ndefTag, (status: NFCNDEFStatus, number: number, error: NSError) => {
console.log('queryNDEFStatusWithCompletionHandler');
// Code omitted for brevity