Search code examples
androidreact-nativeandroid-intentnfcreact-native-nfc-manager

React native: intent changed after requestTechnology called and NFC card scanned


I am currently working on a simple app, which scans an NFC tag and reads the data from it. To implement it, I followed this example here.

For testing, I am using a real android device (Samsung Galaxy J6) and a Mifare NFC card.

At the launch of the app, everything seems fine, the NfcManager has been successfully started, the tag event has been registered (using NfcManager.registerTagEvent),but the problem occurs when requestTechnology has been called and the NFC card scanned.

The difference I noticed is regarding the intent in Android: before running requestTechnology and scanning the card against the phone, the intent and the action attached to it look like this => the action is on the main thread.

After that, the intent and the action look like this.

It seemed strange to me that the action has changed from the main thread.

The Android code is exactly like given in the link above and the code in React Native looks like this:

 _read = async () => {
    try {
      const enabled = await NfcManager.isEnabled();
      console.warn('Enabled: ', enabled);

      await NfcManager.registerTagEvent((tag) => {
        console.warn('Tag Discovered', tag);
      }, 'Hold your device over the tag', true);
  
      let tech = Platform.OS === 'ios' ? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA];
      let resp = await NfcManager.requestTechnology(tech);

      let tag = await NfcManager.getTag()
        .then(() => { console.warn('Tag: ', tag)})
        .catch((err) => console.warn('Tag error: ', err));
     
      {...}

      // this._cleanUp();
    } catch (ex) {
      console.warn(ex);
      this._cleanUp();
    }
  }

Besides that, the method requestTechnology is resolved only if the app is brought to the background and then again to the foreground right away. That also seems strange ...

Does anyone have any idea how to solve these issues and get the NFC card reading process up and running?

I appreciate your help!


Solution

  • I'm not sure why you are looking at the Intent Action as it is of no significance to NFC really.

    Some background of how Android handles NFC should help explain it.

    In Android all Tag detection is handled by a System NFC service/App.

    When you App is not running and a NFC Tag is detected the System Service works out if any App has requested to be started when that type of Tag is seen. It then crafts an Intent to get the System Launcher to launch the main Activity of you app and bundles information about the NFC data in the extras section of the Intent for the System Launcher to pass on in the Intent to your app at Launch time.

    When you are doing requestTechnology your App is already running and you are telling the System NFC Service to pass the NFC data directly to your App, the System Launcher does not need to be involved as your App is already running.

    Now Android has two methods of passing this data directly to your running App, enableForegroundDispatch or the later and much better enableReaderMode.

    You configured react-native-nfc-manager to use the older enableForegroundDispatch which tells the system NFC service to send the Tag details directly to your running Activity. So it does not need to add an Action to tell the system Launcher what to do. But to deliver that Intent with the extras contain data about the Tag directly to your App, the only way for it to do that is to basically restart your App which causes a Pause and Resume.

    But react-native-nfc-manager handles all this for you, so you should not need to worry about what is in the Intent

    Note you can configure react-native-nfc-manager to use enableReaderMode and instead of overloading an Intent to deliver this data to you, if basically creates a Thread in your running App and gives the Thread the Tag data directly and thus does not need to pause and resume your App (plus you get more control of things like NFC detection sound with this newer method)

    So overall the behaviour you are seeing is expected and normal and nothing you should be concerned about or have a problem with.

    Note iOS handles this completely differently but again react-native-nfc-manager handles this via it's iOS specific methods.