Search code examples
androidandroid-fragmentsnfcandroid-architecture-navigation

How to prevent my device reading NFC Tags in every Fragment when using NavigationComponent and a single Activity?


Background

I included Navigation Component in my app which basically means that I have a single Navigation Activity and multiple Fragments that display my Views and Data. The app has the ability to read NFC Tags from ID Cards.

I followed the implementation guide of Android Developers to include the capability of NFC Tag reading and in their example they edit the Activity in the AndroidManifest and enable the ForegroundDispatcher in their Activity. Since I only have a single Activity basically anywhere in my App the NFC Capability is available.

I'm using setIntent(intent) to delegate the incoming Intents to my Fragments. Only the Fragment that is supposed to work with NFC handles the Intent while the others just ignore it.

The Problem

The problem is that when I hold a NFC card close to the phone the phone starts to vibrate since it recognized a NFC device. This happens in every Fragment and is unwanted behavior.

Question

What can i do about this or am I stuck with this behavior? I read a bit about enabling the foregroundDispatcher in a Fragment but the answer was almost always to handle it in my Activity and the function also demands an Activity.


Solution

  • Don't use ForegroundDispatcher (unless you really need to do NFC before API 19) use the newer and better enableReaderMode method instead.

    The Sound is generated by the system NFC App and with enableForegroundDispatch you have no control of the sound plus enableForegroundDispatch has a bad side effect of pausing your App to read the NFC Tag and can be unreliable at times especially if writing to the NFC Tag.

    With enableReaderMode you get to control whether the system NFC App makes a sound or not with the FLAG_READER_NO_PLATFORM_SOUNDS flag.

    So your design will have to change a bit as the onTagDiscovered method is called in another Thread in your application when a NFC Tag is discovered, that thread has to then communicate the data to the Fragment (as it cannot interact with the UI thread directly). One possible method to do this is the onTagDiscovered method in the Activity sets a value in a shared view model and then the Fragment that is interested in it "Observes" this value for change and reacts according including making a sound and vibrate itself.

    Full example of enableReaderMode is at https://stackoverflow.com/a/64921434/2373819

    Note only enabling ForeGroundDispatch NFC in a Fragment is a bad idea, as it is likely the System NFC App will still make a sound anyway when a NFC Tag is presented and because your App might not be handling the event because the Fragment is not running then system NFC App might also show it's own screen over your App as well.