revtel / react-native-nfc-manager

React Native NFC module for Android & iOS
MIT License
1.39k stars 317 forks source link

Use Tech Ndef and NfcA together on Android #666

Closed LucasPiacitelli closed 1 year ago

LucasPiacitelli commented 1 year ago

Hi, I hope you are doing well and thanks for the library.

About the issue, it seems that I'm unable to use Ndef and NfcA techs together. Basically, I'm getting the same errors described by @moony-chen in #661. Even if a solution was already merged in 3.14.8 release, I'm still facing those errors (Error: unsupported tag api and Error: java.lang.ClassCastException: android.nfc.tech.NfcA cannot be cast to android.nfc.tech.Ndef).

The main difference between his issue is that I'm using NXP Ntag213 to perform the tests instead of NTag215 but since I'm new to NFC technology, I can't find the exact problem.

The ideia is set data using Ndef and blocking the tag with password using NfcA

Can anyone help me with that, please?

Code:

        try {
            await NfcManager.requestTechnology([NfcTech.Ndef, NfcTech.NfcA]);
            let tag = await NfcManager.getTag();
            tag.ndefStatus = await NfcManager.ndefHandler.getNdefStatus();

            const bytes = Ndef.encodeMessage([Ndef.uriRecord(url)]);

            if (bytes)
                await NfcManager.ndefHandler.writeNdefMessage(bytes);

            const password = *some password*;

            await NfcManager.nfcAHandler.transceive([0x30, 0x29]);
            await NfcManager.nfcAHandler.transceive([0xa2, 0x29 + 3, 0, 0, 0, 0]);
            await NfcManager.nfcAHandler.transceive([0xa2, 0x29 + 2, ...password]);
            await NfcManager.nfcAHandler.transceive([0xa2, 0x29 + 1, 0, 0, 0, 0]);
            await NfcManager.nfcAHandler.transceive([0xa2, 0x29, 0, 0, 0, 0]);
        } catch (error) {
            Alert.alert(
                'Error saving data',
                error.message ? error.message : 'Something went wrong!'
            );
        } finally {
            await NfcManager.cancelTechnologyRequest();
        }
moony-chen commented 1 year ago

That was just a workaround, so you still need to insert below code before you can call any api on nfcAhandler:

if (isAndroid) {
  await (NfcManager as any).close();
  await (NfcManager as any).connect([NfcTech.NfcA]);
}
LucasPiacitelli commented 1 year ago

That was just a workaround, so you still need to insert below code before you can call any api on nfcAhandler:

if (isAndroid) {
  await (NfcManager as any).close();
  await (NfcManager as any).connect([NfcTech.NfcA]);
}

Oooh, I get it now. When I saw this snippet, I misunderstood where exactly I should insert it. I tested it and it's working fine now. Thank you so much for your help. Will come back to this issue if I need help again but, for now, I'll close it.

amitsingheplanetsoft commented 11 months ago

but with this code we have. to touch nfc chip two times to mobile, what if we want to do this in single touch.

ELichto commented 5 months ago

will it work in the inverse? checking if the password is correct using NfcA then writing using Ndef? I tried but I got [Error: java.io.IOException] when executing writeNdefMessage, the authentification worked

 try {
      await NfcManager.requestTechnology([NfcTech.NfcA, NfcTech.Ndef]);

      await ensurePasswordProtection(); // checking if password is correct using NfcA

      await NfcManager.close();
      await NfcManager.connect([NfcTech.Ndef])

      let bytes = null;
      if (type === 'TEXT') {
        bytes = Ndef.encodeMessage([Ndef.textRecord(value)]);
      } else if (type === 'URI') {
        bytes = Ndef.encodeMessage([Ndef.uriRecord(value)]);
      } else if (type === 'WIFI_SIMPLE') {
        bytes = Ndef.encodeMessage([Ndef.wifiSimpleRecord(value)]);
      } else if (type === 'VCARD') {
        const { name, tel, org, email } = value;
        const vCard = `BEGIN:VCARD\nVERSION:2.1\nN:;${name}\nORG: ${org}\nTEL;HOME:${tel}\nEMAIL:${email}\nEND:VCARD`;

        bytes = Ndef.encodeMessage([
          Ndef.record(Ndef.TNF_MIME_MEDIA, 'text/vcard', [], vCard),
        ]);
      }

      if (bytes) {
        console.log('before writing!', bytes) // logged
        await NfcManager.ndefHandler.writeNdefMessage(bytes);
        console.log('after write'); / not logged

        if (Platform.OS === 'ios') {
          await NfcManager.setAlertMessageIOS('Success');
        }

        result = true;
      }
    } catch (ex) {
      handleException(ex);
    } finally {
      NfcManager.cancelTechnologyRequest();
    }