2
votes

I have a react-native app which reads NFC tags and writes a URL to them. It uses ForegroundDispatch to make sure the app captures the scanned info and doesn't navigate away to the browser when the link is detected. The link is used only when the app is not launched, it opens a browser and shows information from my server to the external user.

When I'm in the app and I turn the screen off (power button), then turn it back on again and scan an NFC tag, the browser opens up. It looks like the scanned intent doesn't deliver to the app and is instead handled by the phone as default. After the first scan, which opens the browser, I navigate back to the app and the following scans work fine inside the app.

Here is the twist: on most phones it works as expected. Works on Pixel 3 (Android 9), on Huawei (Android 5.1) on Sony (Android 7) an a few others. But when I use UleFone X2 (http://ulefone.com/product.html) this issue occurs. Am I doing something incorrectly to initialize the app so it handles itself the same every time, even when it's resumed?

From my research it looks like UleFone disables NFC when the screen goes off and when it turns back on, am I not initializing it properly? If I open the recent apps and navigate away from my app, then back into it, the NFC starts working.

This is my main activity:

public class MainActivity extends ReactActivity {
    private NfcAdapter mAdapter;
    private PendingIntent mPendingIntent;
    private IntentFilter[] mFilters;
    private String[][] mTechLists;
    private int mCount = 0;

    @Override
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    }

    @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        mAdapter = NfcAdapter.getDefaultAdapter(this);
        mPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        };
        mFilters = new IntentFilter[] {
                ndef,
        };
        mTechLists = new String[][] { new String[] {NfcA.class.getName()}, new String[] {MifareClassic.class.getName()}, new String[] {Ndef.class.getName()},   };
        Log.d("scantest", "onCreate completed");
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mAdapter != null) mAdapter.disableForegroundDispatch(this);
        Log.d("scantest","onPause completed");
    }

    @Override
    public void onResume() {
        super.onResume();
        Intent intent = getIntent();
        if (mAdapter != null) mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
        Log.d("scantest","onResume completed");
    }

Expected behaviour: All Android phones that support NFC handle NFC scanning in the app the same way, on launch and after it is resumed. The intent should always deliver to my app.

Current behaviour: Most phones work fine after screen goes off/on again. On some phones (UleFone) if I turn the screen off/on, the first scan opens the browser, and the following ones work inside the app.

Current workaround:

After turning screen off/on, if I navigate away from the app using recent apps (I don't even have to click on another app, just have to make sure the recent apps tiles come up) then click to go back to my app, NFC doesn't fail on the first scan.

Otherwise the first scan fails and opens the browser.

1

1 Answers

1
votes

A workaround could be to add this intent-filter to your activity https://developer.android.com/guide/topics/connectivity/nfc/nfc#tag-disc

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

With this you declare to android your app is want to catch any NFC tag. If device has another app which catch nfc tag, then a menu is shown to user to select which app get NFC intent.