the app i'm working on ought to receive a beam and then call the processIntent(intent) function from onResume. the problem i'm having is that when it receives the beam, it opens a completely new instance of the app instead of just staying within the activity (i've already called enableForegroundDispatch).
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null){
Toast.makeText(this, "No NFC on this device", Toast.LENGTH_LONG).show();
}
// Create a PendingIntent object so the Android system can populate it with the details of the tag when it is scanned.
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// Declare intent filters to handle the intents that the developer wants to intercept.
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("application/com.sample.mime/string");
} catch (MalformedMimeTypeException e) {
Log.wtf("mimeexception", e);
e.printStackTrace();
}
intentFiltersArray = new IntentFilter[] {ndef};
... ...
}
public void onResume() {
super.onResume();
// Enable the foreground dispatch when the Activity regains focus.
NfcAdapter.getDefaultAdapter(this).enableForegroundDispatch(this, pendingIntent, intentFiltersArray, null);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
processIntent(getIntent());
}
}
public void onPause() {
super.onPause();
// Disable the foreground dispatch when the Activity loses focus.
NfcAdapter.getDefaultAdapter(this).disableForegroundDispatch(this);
}
void processIntent(Intent intent){
// do stuff
}
and here's the activity from the manifest
<activity
android:name="com.example.app.opensthisonebutshouldnt"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.app.shouldopenthisone"
android:label="@string/title_activity_create_invoice"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />\
<category android:name="android.intent.category.DEFAULT" />\
<data android:mimeType="application/com.example.nfctest/invoice" />
</intent-filter>
</activity>
thanks for the input
application/com.sample.mime/string
(used in ndef.addDataType(...);
) does not look like a valid MIME type. Are you sure that you are Beaming this type? Even if you do, I'm not sure that Android will be able to process it. A valid MIME type that comes close to yours would be application/com.sample.mime
(without the /string
part). The same applies to the /invoice
part of application/com.example.nfctest/invoice
.
If your foreground dispatch intent filter does not match the first record of the Beamed NDEF message, your app may receive NFC events according to intent filters in your manifest. Note that NDEF_DISCOVERED
intent filters only match the first record of an NDEF message.
If the Beamed message contains an AAR (Android Application Record) and none of your NFC-related intent filters matches the first record of the Beamed NDEF message, the first activity declared in your manifest that has an intent filter for actuion MAIN
with category LAUNCHER
will be started. This seems to happen in your case. So double check that your foreground dispatch actually matches the incoming NDEF message. Otherwise your activity may be re-launched according to the definitions in your app manifest.
Checking getIntent()
in onResume()
will only check the intent currently associated with your activity (i.e. the intent that initially started your activity or that has been registered using setIntent(...)
) when your activity is resumed. However, events from the foreground dispatch that you registered will arrive in your activity's onNewIntent()
method. So you need to override that method and process the NFC event there:
@Override
public void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
processIntent(intent);
}
}