How to launch activity with NFC and then allow different tags to be scanned on same activity?

385 Views Asked by At

I have a basic Android application and need to implement the ability for an NFC swipe to launch a specific Activity. I have achieved this by writing an Android Application Record. I then need for further swipes to use the same Activity rather than launching new ones.

The Android Application Record launches the Activity as expected. I then fire up a create a Pending Intent and in OnResume, set up a foreground dispatch

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

    // initialize NFC
    nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
}

@Override
protected void onResume() {
    Log.d(TAG, "onResume");

    super.onResume();

    enableForegroundMode();

    doTagOperations(getIntent());
}

public void enableForegroundMode() {
    Log.d(TAG, "enableForegroundMode");

    IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); // filter for all
    IntentFilter[] writeTagFilters = new IntentFilter[] {tagDetected};
    nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
}

I then have a method that does tag related activities. This looks as follows:

private void doTagOperations(Intent intent) {

    Log.i(TAG, intent.getAction());
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        TextView textView = (TextView) findViewById(R.id.title);

        textView.setText("Hello NFC!");

        Parcelable[] messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (messages != null) {

            Log.d(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one

            vibrate(); // signal found messages :-)

            // parse to records
            for (int i = 0; i < messages.length; i++) {
                try {
                    List<Record> records = new Message((NdefMessage)messages[i]);

                    Log.d(TAG, "Found " + records.size() + " records in message " + i);

                    for(int k = 0; k < records.size(); k++) {
                        Log.d(TAG, " Record #" + k + " is of class " + records.get(k).getClass().getSimpleName());

                        Record record = records.get(k);
                        if(records.get(k).getClass().getSimpleName().equals("TextRecord")) {
                            String plant = new String(records.get(k).getNdefRecord().getPayload());
                            Log.i(TAG, plant);
                            textView.setText(plant);
                        }
                        if(record instanceof AndroidApplicationRecord) {
                            AndroidApplicationRecord aar = (AndroidApplicationRecord)record;
                            Log.d(TAG, "Package is " + aar.getDomain() + " " + aar.getType());
                        }

                    }
                } catch (Exception e) {
                    Log.e(TAG, "Problem parsing message", e);
                }

            }
        }
    } else {
        // ignore
    }
}

My issue is that the system behaves in an odd way. You can launch the Activity with the tag but a second swipe will launch a new Activity. Further swipes will then use the existing Activity but the Intent will always appear to be the same. I attempt to read a text record from the tag and this should change based on the tag I have swipe - but it doesn't. It's as if the method by which I grab the Intent is always picking up the same one irrespective of the tag swiped.

1

There are 1 best solutions below

0
Michael Roland On

Getting the fresh intent from the NFC foreground dispatch

In onResume() you retrieve the intent with getIntent(). Unless you overwrite this intent with setIntent(), getIntent() will return the intent that initially started your activity.

The fresh intent from the NFC foreground dispatch system is delivered to your activity through the onNewIntent() method. Therfore, you could do something like this:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    doTagOperations(intent);
}

The second NFC event launches a new instance of the activity

I'm not qute sure about that one, but my might want to try to experiment with setting the lauchMode for your activity. See this answer to the question NFC Tag Reading. You could also try if the alternative approach to using the foreground dispatch system (using createPendingResult() and onActivityResult()) works in this situation. See my other answer here.