0

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

Han
  • 140
  • 6
  • It looks like that plugin is already compatible with 7+. When you say upgrade the plugin to 7/8 what are you changing? Also, what JavaScript versions are you targeting. If you are using TypeScript targeting es2015+, are you using `ts-patch`? – RcoderNY Sep 29 '21 at 10:47
  • @RcoderNY Thanks for your reply, I edited the question so now you can see the whole source code. The original plugin supports 7+ without writing feature, I implemented the write part based on version 4.1 which is NS 6. When upgrading to 7/8, I basically rebased from version 5.0 and added my implementation. I added `@NativeClass` and also use `ts-patch` – Han Sep 30 '21 at 13:30

1 Answers1

0

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
Han
  • 140
  • 6