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?
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
FFFEas the max size when in fact the max size according to the spec is80FEand 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
80FEaccording to the spec it seems that7FFF(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