A software noob A software noob - 1 month ago 13
Android Question

NFC foreground dispatch not working

I'm trying to make it so that when I open my app and scan a tag, it will display a toast with the ID of the tag. The problem is, every time I scan a tag it brings up a list of applications and I can choose mine among them.

I tried to implement the foreground dispatch mechanism, but then it does not show anything at all (it neither crashes, nor does it display the toast).

This is the main code:

public class loginPage extends AppCompatActivity {
NfcAdapter mAdapter;
PendingIntent pendingIntent;
private String serialId = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_page);
mAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
if (mAdapter == null) {
Toast.makeText(this,
"NFC NOT supported on this devices!",
Toast.LENGTH_LONG).show();
finish();
} else if (!mAdapter.isEnabled()) {
Toast.makeText(this,
"NFC NOT Enabled!",
Toast.LENGTH_LONG).show();
finish();
}
}

@Override
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
@Override
public void onPause(){
super.onPause();
mAdapter.disableForegroundDispatch(this);

}
@Override
public void onNewIntent(Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String action = intent.getAction();
if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
try {
byte[] tagId = tag.getId();
serialId = toHexString(tagId);
Log.d("[ReadCardTools]", "Serial Number: " + serialId);
Toast.makeText(this, serialId, Toast.LENGTH_SHORT).show();
} catch (NullPointerException ex) {
ex.printStackTrace();
serialId = "ERROR";
}
}
}

public static String toHexString(byte[] bytes) {
char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v / 16];
hexChars[j * 2 + 1] = hexArray[v % 16];
}
return new String(hexChars);
}
}


The manifest contains the following additions:

<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"
android:required="true"/>


and

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


The filter is:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcF</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcV</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NdefFormatable</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareClassic</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>


logcat only says "D/PersonaManager: isNFCAllowed" every time I scan a tag.

Answer Source

The foreground dispatch system, when enabled as a catch-all (i.e. with the last two arguments of the method enableForegroundDispatch() set to null), will send TAG_DISCOVERED intents to your activity. Since you only listen for TECH_DISCOVERED intents (and ignore all others) you won't display the toast upon tag discovery.

You will therefore need to also act upon receiving a TAG_DISCOVERED intent in onNewIntent:

@Override
public void onNewIntent(Intent intent) {
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) ||
        NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null) {
            serialId = toHexString(tag.getId());
            Log.d("[ReadCardTools]", "Serial Number: " + serialId);
            Toast.makeText(this, serialId, Toast.LENGTH_SHORT).show();
        }
    }
}