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.
Getting the fresh intent from the NFC foreground dispatch
In
onResume()you retrieve the intent withgetIntent(). Unless you overwrite this intent withsetIntent(),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: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()andonActivityResult()) works in this situation. See my other answer here.