I am working on an app that is in its final stages when I was asked to make changes to it to read the unique serial number of NFC tags. No big problem there, however in the case of some of the tags the serial number is returned as null.
When using the NFC Tools app to inspect the tag the serial number is there but intent.getByteArrayExtra()
method called with NfcAdapter.EXTRA_ID
as parameter returns null
in the case of those tags.
Below you have my Android manifest and the code I used to get the UID if it helps.
@Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
// New code to deal with multiple tag versions (supports NfcA, NDEF, MifareUltralight)
// parse tech list
byte[] uid = getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID);
String serialNumber = uidByteToHexString(uid);
if (serialNumber != null && !serialNumber.isEmpty()) {
return serialNumber;
}
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="myPackageName here" >
<!-- Application permissions go here, mainly NFC -->
<uses-permission android:name="android.permission.NFC" />
<users-feature android:name="android.hardware.nfc" android:required="true"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MyActivityNameHere"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/FullscreenTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- NFC Intent Filters -->
<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.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_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" />
</activity>
</application>
</manifest>
My other question is: When reading tags some tags trigger the chooser dialog making me choose which application do I want to use to process the tag. Would it be possible to eliminate that and have just my app deal with NFC events while it is active?
The tags I am using are NfcA, MifareUltralight and Ndef. If it helps.
When
getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID)
returnsnull
, this means thatgetIntent()
is not an NFC intent. Given the manifest that you posted (and assuming that the above code is used inMyActivityNameHere
), this means thatgetIntent()
gives you either a launcher intent (action MAIN with category LAUNCHER) or an explicit intent).Typically, this could have two reasons:
Your activity was started by clicking its launcher icon (or from another activity/component). You later scanned an NFC tag and that event was delivered through the
onNewIntent()
method (e.g. because you registered for the foreground dispatch system) but you did not update the activity's intent field withsetIntent()
. In that case,getIntent()
would still return the intent that initially started the activity and not the NFC intent that you received later on.The NFC tag contains an Android Application Record (AAR) but its first record is not a text/plain record. As your NDEF_DISCOVERED intent filter requires a text/plain NDEF record as first record, Android does not know that your activity supports that type of tag and consequently starts your app using a MAIN+LAUNCHER intent instead of an NFC intent. Therefore, this intent will neither contain the tag ID nor a handle to the tag.
You can check the type of the intent with
intent.getAction()
. For an NFC intent, this would return one ofandroid.nfc.action.NDEF_DISCOVERED
,android.nfc.action.TECH_DISCOVERED
, orandroid.nfc.action.TAG_DISCOVERED
.Regarding the intent chooser dialog, I suggest that you read through How NFC Tags are Dispatched to Applications. This document thouroughly explains how applications get priority for NFC intents.