0

I am currently working on a simple app for scanning, reading data from an NFC card (in my case a Mifare NFC card) and displaying in on the screen. I have built it using this example.

The app should work both on Android and iOS, but for the moment, I have tested it only on an android device (an Oppo device with NFC capablities and developer mode activated).

At the launch of the app, everything seems to be working fine, the NfcManager has been successfully started, but there is an issue when the app tries to request the technology for reading the card, namely, I have to bring the app first in the background and then again in the foreground so that the message requestTechnology success is displayed, otherwise, it's simply not called.

After this, the promise NfcManager.getTag() gets rejected with the error message: no reference available.

Here is my code:

componentDidMount() {
    NfcManager.start({
      onSessionClosedIOS: () => {
        alert('ios session closed');
      },
    }).then(() => console.warn('NfcManager started')) // successfully started
    .catch((error) => alert('Error starting NfcManager: ', error));

}

{... componentWillUnmount and render method ...}

 _read = async () => {
    try {
      let tech = Platform.OS === 'ios' 
        ? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA, NfcTech.IsoDep, NfcTech.Ndef];
      let resp = await NfcManager.requestTechnology(tech, {
        alertMessage: 'Ready to do some custom Mifare cmd!'
      })
      .then((value) => alert('requestTechnology success', value)) // here the value is empty, so no NfcTech
      .catch(() => console.warn('reuqestTechnology error'));

      const tag = await NfcManager.getTag()
      .then((value) => alert('Tag event: ', value))
      .catch((err) => console.warn('error getting tag: ', err));

      // this part of the code is reached, but not working properly since the tag.id is not correctly retrieved
      if (Platform.OS === 'ios') {
         resp = await NfcManager.sendMifareCommandIOS([0x30, 0x00]);
      } else {
         resp = await NfcManager.transceive([0x30, 0x00]);
      }
      console.warn('Response: ', resp);
      this._cleanUp();
    } catch (ex) {
      console.warn(ex);
      this._cleanUp();
    }
  }

If I scan the card against the device, it makes the sound like it has been scanned, but nothing seems to be displayed.

Does anyone know why does the app needs to be brought to the background so that the technology is requested? And second, does the fail of the getTag() method have anything to do with it?

I hope anyone can help me with this issue, I have been struggling with this problem for quite some time and I haven't found any solution.

Yennefer
  • 5
  • 4
  • I hope you are using await in the right way!, can you share the whole function code? – Akshay Shenoy Jan 09 '22 at 13:23
  • @AkshayShenoy sure, I have updated it above – Yennefer Jan 09 '22 at 13:31
  • Have you started the NfcManager ? **NfcManager.start();** – Akshay Shenoy Jan 09 '22 at 13:37
  • Yes, I have started it inside the method componentDidMount and it started successfully, I have updated the code above with the method – Yennefer Jan 09 '22 at 13:39
  • @AkshayShenoy what I have also noticed is that in the then branch of the requestTechnology method, the value of the NfcTech is undefined, even if the promise is resolved – Yennefer Jan 09 '22 at 13:54
  • If I would have a button which calls the following method: _request = async () => `{ let tech = Platform.OS === 'ios' ? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA, NfcTech.IsoDep, NfcTech.Ndef]; let resp = await NfcManager.requestTechnology(tech, { alertMessage: 'Ready to do some custom Mifare cmd!' }) .then((value) => alert('requestTechnology success', value)) .catch(() => console.warn('reuqestTechnology error')); console.warn(resp); }` I get the same behavior ... – Yennefer Jan 09 '22 at 13:57
  • Can you try just `NfcManager.requestTechnology(tech, { alertMessage: 'Ready to do some custom Mifare cmd!' }) .then((value) => alert('requestTechnology success', value)) // here the value is empty, so no NfcTech .catch(() => console.warn('reuqestTechnology error'));` instead using an await and storing it in resp? – Akshay Shenoy Jan 09 '22 at 14:09
  • @AkshayShenoy I tried doing that, but I get the same behavior: `alert('requestTechnology success', value))` is displayed only after the same procedure of bringing the app in the background and then back in the foreground – Yennefer Jan 09 '22 at 14:52
  • If I do like you suggested `let resp = null; NfcManager.requestTechnology(tech, { alertMessage: 'Ready to do some custom Mifare cmd!' }) .then((value) => { alert('requestTechnology success', value); resp = value; }) // here the value is empty, so no NfcTech .catch(() => console.warn('reuqestTechnology error')); console.warn(resp);` the resp is displayed imediately, but it's null – Yennefer Jan 09 '22 at 14:52
  • As an update: inside the then branch of the NfcManager.start(), I tried calling NfcManager.isEnabled().then((value) => alert(value)), but the alert box contains nothing. Does that mean that the manager is not actually started? – Yennefer Jan 09 '22 at 15:10
  • Ok, whats the value of resp if you just write, ‘let resp = await NfcManager.requestTechnology(tech):’ – Akshay Shenoy Jan 09 '22 at 15:21
  • At first nothing is displayed and after I move the app from background to foreground, then it's null. If I call for example isEnabled the same way I do with the requestTechnology, I get a response (empty though) without doing any futher actions with the app. – Yennefer Jan 09 '22 at 15:31
  • @AkshayShenoy maybe the example I used is a little old and it does not work anymore or maybe I do something wrong in my code (shouldn't be the case since it's the exact same code as in the example). Do you have any idea where I could find a working solution, so that I don't waste your time with (perhaps) a buggy code? – Yennefer Jan 09 '22 at 15:36
  • Hmm yeah, https://github.com/revtel/react-native-nfc-manager , maybe you can check if the you have followed all the steps properly, also in case of android, instead of array of NfcTech, just give NfcTech.Ndef, and check. – Akshay Shenoy Jan 09 '22 at 16:37

1 Answers1

0

May be related to github.com/revtel/react-native-nfc-manager/issues/423 ?? there seems to be a scenario where this package does not correctly configure enableForegroundDispatch and manually pausing and resuming the App by sending it to the background would fix it.

Andrew
  • 8,198
  • 2
  • 15
  • 35