Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Listening to NFC Adapter State Changed

I am trying to build an application which uses NFC. The goal is to display a DialogFragment containing a button link to go the settings and change it manually and when the feature is enabled, disable the DialogFragment.

Problem: If the user enables/disables NFC using the icon in the pull down notifications tray , then the onPause/onResume doesn't get called and misses the condition entirely. I am sure there is a receiver that I can register to instead and respond appropriately in real time. Any ideas, thoughts or reference will be greatly appreciated!

The following code checks if the state is enabled/disabled. I am also responding to it appropriately in the onResume event.

    NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
    NfcAdapter adapter = manager.getDefaultAdapter();

    if(adapter != null && adapter.isEnabled()) {
        detector = new NfcDetector(this);
        detector.setListener(this);
        onNfcFeatureFound();
    }
    else {
        onNfcFeatureNotFound();
    }

For others looking at this post, the code below will take the user directly into settings to enable/disable NFC:

startActivity(new Intent(android.provider.Settings.ACTION_NFC_SETTINGS));
like image 319
ahmad Avatar asked Sep 11 '13 15:09

ahmad


2 Answers

Thought I should post the answer for other people looking for the same problem, since I wasn't able to find one easily.

Add the following code to your activities onCreate() method:

IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
this.registerReceiver(mReceiver, filter);

Inner private class declared within your activity (or anywhere else you like):

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (action.equals(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)) {
            final int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
                                                 NfcAdapter.STATE_OFF);
            switch (state) {
            case NfcAdapter.STATE_OFF:
                break;
            case NfcAdapter.STATE_TURNING_OFF:
                break;
            case NfcAdapter.STATE_ON:
                break;
            case NfcAdapter.STATE_TURNING_ON:
                break;
            }
        }
    }
};

@Override
public void onDestroy() {
    super.onDestroy();

    // Remove the broadcast listener
    this.unregisterReceiver(mReceiver);
}

  // The following check needs to also be added to the onResume
@Override
protected void onResume() 
    super.onResume();
    // Check for available NFC Adapter
    NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);

    if(adapter != null && adapter.isEnabled()) {
        createNfcDetector();
        //NFC is available on device, but disabled
    }
    else {
        //NFC Is available and enabled
    }
}
like image 52
ahmad Avatar answered Oct 28 '22 21:10

ahmad


You can use ACTION_ADAPTER_STATE_CHANGED to receive a broadcast message when the state of the adapter changes, but that option is only available in API 18 and above. See this for the documentation.

For prior to 18, I don't know of a way to do this unfortunately.

Also, as an aside, the android.provider.Settings.ACTION_NFC_SETTINGS will work on API levels 16 and above. For prior versions, the NFC settings are under "wireless settings". Take a look at the ensureSensorIsOn method at the bottom of this blog post for a code sample that checks against the API level and redirects to the correct settings pane.

like image 22
Ameen Avatar answered Oct 28 '22 22:10

Ameen