androidtagsnfcndef

Reading a message stored on NDEF tag. Android


I was trying to find a working example of how it is possible to read a message stored on a NDEF tag within the app's active Activity. By far the best I have is such a code:

public class Activity1_3_1_1 extends AppCompatActivity {

private Button done;
NfcAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity1_3_1_1);

    done = findViewById(R.id.button5);

    done.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switchActivityTo1();
        }
    });
}

private void switchActivityTo1() {
    Intent switchActivityIntent = new Intent(this, MainActivity.class);
    startActivity(switchActivityIntent);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        adapter = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  // get the detected tag
        Parcelable[] msgs =
                intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        NdefRecord firstRecord = ((NdefMessage) msgs[0]).getRecords()[0];
        byte[] payload = firstRecord.getPayload();
        int payloadLength = payload.length;
        int langLength = payload[0];
        int textLength = payloadLength - langLength - 1;
        byte[] text = new byte[textLength];
        System.arraycopy(payload, 1 + langLength, text, 0, textLength);
        Toast.makeText(getApplicationContext(), new String(text), Toast.LENGTH_LONG).show();//display the response on screen
    }
}
}

And the Manifest file:

...
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"/>
...
        <activity
        android:name=".Activity1_3_1_1"
        android:exported="true"
        android:alwaysRetainTaskState="true"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

The problem is that NFC Service is launching instead of app's onNewIntent() method. And it is a problem for me figuring out am I messed up with Manifest file definition (because one of solutions was to modify Manifest file in order to NFC Service won't launch) or it is problem inside the Activity code itself. Or, perhaps, both.


Solution

  • So the normal pattern for NFC in Android is:-

    1)When you App is not running an you want it started when a certain type of NFC Tag is presented to the device then you put your intent-filters in the manifest. Your App then gets started and passed an Intent that you need to process in your onCreate method using getIntent()

    2a)Your App is already running in the foreground then you use enableForegroundDispatch, giving it a pending Intent on what you want to be notified about, this is then processed in onNewIntent when your App is restarted (paused and resumed) to receive the Intent.

    onNewIntent won't get invoked by any manifest entry.

    or

    2b)Your App is already running in the foreground then you use enableReaderMode which is a better replacement for enableForegroundDispatch, you then process the Tag in onTagDiscovered which is in a separate thread.

    How to process the Intent received via pattern 1 and 2a is the same, just they need to be called from the correct path in the code that matches the method that triggered the Intent i.e in onCreate or in onNewIntent

    Check out Empty NFC Tag read and write Android Application. Mobile own message returning while scanning Empty Tag but Application not working? for an example of how to use Manifest and enableForeGroundDispatch

    The are also plenty examples of using enableReaderMode on Stackoverflow as well.