Why does data transfer over NFC with HCE only work with Android lower 12?

964 Views Asked by At

I am trying to send data (to keep it simple at first just a NDEF text message) between two Android devices with a React Native App. In order to do that I emulate an NFC tag on one device with the react-native-hce Library and read this tag on the other device with the react-native-nfc-manager Library.

Here is the NFC-relevant code:

  async function sendData() { 
    const tag = new NFCTagType4({
      type: NFCTagType4NDEFContentType.Text,
      content: 'Hello World',
      writable: true
    });
    session = await HCESession.getInstance();
    session.setApplication(tag);
    await session.setEnabled(true).catch((err) => console.log(err));
  }

  async function stopSending() {
    if(session)
       await session.setEnabled(false)
  }

  async function readNdef() {
    stopSending()
    NfcManager.requestTechnology(NfcTech.Ndef)
      .then(() => NfcManager.getTag())
      .then(tag => {
        if(tag) {
          let text = String.fromCharCode(...tag.ndefMessage[0].payload)
          Alert.alert("Message received", text)
        }
      })
      .catch(err => {
        console.warn(err)
      })
      .then(() => {NfcManager.cancelTechnologyRequest()})
  }

I tested my app with several devices I got:

Old Sony Xperia (Android 8), Samsung Galaxy A50 (Android 11), Huawei P30 Lite (Android 11): Working perfectly fine.

Motorola Edge 30 Fusion (Android 12), Samsung Galaxy A41 (Android 12): Not working. HCE just isn't working (without any error) and reading an emulated tag works basically, but there is no NDEF message read although it exists (also the App TagInfo is able to read NDEF). With normal, non-emulated tags it works fine.

It seems like Android 12 has problems with reading emulated tags and HCE. Maybe it's a problem of the React Native Libraries? Does anyone have an idea to solve this?

1

There are 1 best solutions below

3
Andrew On

Might be related to the answer in https://stackoverflow.com/a/75676725/2373819 it seems that the Type 4 NFC spec is not clear as it should be on the max size of an Ndef message.

I think that a lot of previous code used FFFE as the max size when in fact the max size according to the spec is 80FE and now Android might be treating the capability container with an invalid max size as bad.

This is a theory as I have no way to test it (I don't have access to an Android 12 or higher device)

Update

While the practical limit is 80FE according to the spec it seems that 7FFF (or 32K) is a more logical limit and this matches a number that is more likely for a physical Tag's memory size, and comments show some success.

And thus the line

byte[] controlTlv = BinaryUtils.HexStringToByteArray("0406E104FFFE00" + (prefManager.getWritable() ? "00":"FF"));

In the library should be

byte[] controlTlv = BinaryUtils.HexStringToByteArray("0406E10480FE00" + (prefManager.getWritable() ? "00":"FF"));

(also the line public final byte[] ndefDataBuffer = new byte[0xFFFE]; in the same file should have the same size change)

The library does have an issue for this