NFC tag detection does not call onNewIntent and it starts from main activity

I am new to NFC. I tried to connect to NFC and transfer text data from the device to another device.

I install my application on both devices, and on one device I open the application and start pushing the device to another device to transfer data through Beam.

On another device, my application opens due to interaction with Beam. However, activity starts with the default MAIN action, and not with TAG_DISCOVERED (or a similar NFC intent). Each time he does the same.

In addition, it does not call the onNewIntent() method. I tried calling onNewIntent from onCreate , but in this case the intent action remains MAIN. I was expecting to get an NFC intent for Beam interaction. So please tell me where I made a mistake?

In this code I am not sharing data. First I need a tag.

manifest:

 <activity android:name="com.framentos.hellonfc.MainActivity" android:clearTaskOnLaunch="true" android:label="@string/app_name" android:launchMode="singleTop" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity> 

Java Code:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ctx = this; // startHandler(); _handler = new Handler(); Button btnWrite = (Button) findViewById(R.id.button); message = (TextView) findViewById(R.id.nfcwriteTag); btnWrite.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); adapter = NfcAdapter.getDefaultAdapter(this); if (adapter == null) { message.setText("NFC is not supported on this device."); } if (adapter.isEnabled()) { message.setText("NFC is Enabled on this device."); } else { message.setText("Please enable NFC to communicate."); } pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter tagDetected = new IntentFilter( NfcAdapter.ACTION_NDEF_DISCOVERED); tagDetected.addCategory(Intent.CATEGORY_DEFAULT); IntentFilter tagTech = new IntentFilter( NfcAdapter.ACTION_TECH_DISCOVERED); tagTech.addCategory(Intent.CATEGORY_DEFAULT); IntentFilter tagDetect = new IntentFilter( NfcAdapter.ACTION_TAG_DISCOVERED); tagDetect.addCategory(Intent.CATEGORY_DEFAULT); writeTagFilters = new IntentFilter[] { tagDetected, tagTech ,tagDetect}; // handleIntent(getIntent()); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.i(getPackageName(), "on New Intent is called...!"); handleIntent(getIntent()); } public void onPause() { super.onPause(); WriteModeOff(); } @Override public void onResume() { super.onResume(); WriteModeOn(); } private void WriteModeOn() { writeMode = true; adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null); } private void WriteModeOff() { writeMode = false; adapter.disableForegroundDispatch(this); } 
+8
android nfc android-beam android-applicationrecord nfc-p2p
source share
1 answer

From the code you posted in your question, I assume that you have not registered your application to send a specific NDEF message. In this case, if your application is open on one device, Android will automatically send an NDEF message containing a URI record with the Play Store link of your application and the recording of Android applications (AAR) to another device.

So, your second device will receive the following NDEF message:

 +---------------------------------------------------------------------------------------+ | WKT:URI | http://play.google.com/store/apps/details?id=your.package.name&feature=beam | +---------------------------------------------------------------------------------------+ | EXT:android:com:pkg | your.package.name | +---------------------------------------------------------------------------------------+ 

What happens if your application is not already open on the second device, this means that recording the Android application (second record) will cause your application to start. However, looking at your manifest, you do not have an intent filter that matches the first record of this NDEF message (Play Store URL). Therefore, Android believes that you do not expect an NDEF message and use the standard android.intent.action.MAIN (with the category android.intent.category.LAUNCHER ) to launch your application (or, rather, the first action of your application that has a filter intent for MAIN action with category LAUNCHER ).

In order to get the NFC intent along with the entire NDEF message in your application, you will need to define a filter of the correct intent, corresponding to the first entry in the above NDEF message:

 <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="http" android:host="play.google.com" android:pathPrefix="/store/apps/details?id=your.package.name" /> </intent-filter> 

Now Android will know that your application / event is ready to receive the NFC intent and pass the NDEF_DISCOVERED intent for your activity. Please note that you still will not get this intention through onNewIntent() if your application is not already running. Instead, you can get the intent that started your activity using the getIntent() activity method. For example. in onCreate / onStart / onResume , you can use

 Intent intent = getIntent(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { NdefMessage ndefMessage = null; Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if ((rawMessages != null) && (rawMessages.length > 0)) { ndefMessage = (NdefMessage)rawMessages[0]; } // TODO: do something with the received NDEF message } 

to get the intent and message NDEF.

As for the intent filters you already have in your manifest:

  • NDEF_DISCOVERED :

     <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> 

    The NDEF_DISCOVERED intent NDEF_DISCOVERED without the <data ... /> will never fire on many NFC devices. You should always determine what specific data you expect to be present in the running NDEF record.

  • TECH_DISCOVERED :

     <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> 

    This intent filter should only be used if you do not start the application when a specific NFC tag technology is detected (you define specific technologies in the nfc_tech_filter.xml file. For your Beam script, you will not use such an intent filter. Btw. <category ...> Category tag <category ...> not used for this target filter.

  • TAG_DISCOVERED :

     <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> 

    This intent filter should not normally be used in a manifest. This is meant as a backup that runs if no other application can process the detected NFC tag. Using this can lead to a bad user experience (for example, the application starts for tags that it cannot or does not want to process). It is mainly available for backward compatibility with API level 9 (?).

To also catch the intent of NFC, if your activity is already running, you can register to send the foreground like this (in the onResume method):

 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null); 

In this way, you will receive any NFC detection events that occur when your activity is in the foreground in your action. onNewIntent . They will be sent via ACTION_TAG_DISCOVERED .

+25
source share

All Articles