Jonas Mohr Pedersen
Jonas Mohr Pedersen

Reputation: 555

Running NFC app on different devices results in inconsistency parsing EXTRA_NDEF_MESSAGE

I am having an issue with NFC in a project I am currently making for school. It is the first time I try to use NFC in an application and might therefore not have a proper understanding of how it works.

The issue is that we have been testing the application on a HTC One M8 for the past week, where our application had no problems reading the string on our chip.

However when I'm now trying with a family member's LG Nexus 5, the string does not get passed to the application.

Here is the code:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_app);
    //NFC Adapter
    nfcAdapter = NfcAdapter.getDefaultAdapter(this);
}

@Override
protected void onResume() {
    super.onResume();
    enableForegroundDispatchSystem();
}

@Override
protected void onPause() {
    super.onPause();
    disableForegroundDispatchSystem();
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
        Toast.makeText(this, "NfcIntent!", Toast.LENGTH_SHORT).show();

        Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (parcelables != null && parcelables.length > 0) {
            // this part gets executed on the HTC Once m8
            readTextFromMessage((NdefMessage) parcelables[0]);
        } else {
            // this part gets executed on the LG Nexus 5
            Toast.makeText(this, "No NDEF messages found!", Toast.LENGTH_SHORT).show();
        }
    }
}

private void readTextFromMessage(NdefMessage ndefMessage) {
    NdefRecord[] ndefRecords = ndefMessage.getRecords();
    if (ndefRecords != null && ndefRecords.length>0) {
        NdefRecord ndefRecord = ndefRecords[0];

        String tagContent = getTextFromNdefRecord(ndefRecord);
        if (tagContent.toString().equals("Kasse")) {
            //scanBtn.setVisibility(View.VISIBLE);
        } else {
            //addItem(tagContent);
            //cartArrayDisplay.addView(nameList.get(cartAmount));
            //priceArrayDisplay.addView(priceList.get(cartAmount));
            //cartAmount++;
        }
    } else {
        Toast.makeText(this, "No NDEF records found!", Toast.LENGTH_SHORT).show();
    }
}

private void enableForegroundDispatchSystem() {
    Intent intent = new Intent(this, AppActivity.class).addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    IntentFilter[] intentFilters = new IntentFilter[]{};
    nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null);
}

private void disableForegroundDispatchSystem() {
    nfcAdapter.disableForegroundDispatch(this);
}

public String getTextFromNdefRecord(NdefRecord ndefRecord) {
    String tagContent = null;
    try {
        byte[] payload = ndefRecord.getPayload();
        String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
        int languageSize = payload[0] & 0063;
        tagContent = new String(payload, languageSize + 1,
                payload.length - languageSize - 1, textEncoding);
    } catch (UnsupportedEncodingException e) {
        Log.e("getTextFromNdefRecord", e.getMessage(), e);
    }
    return tagContent;
}

When run the app on the HTC One m8 it would always run this part:

if (parcelables != null && parcelables.length > 0) {
    readTextFromMessage((NdefMessage) parcelables[0]);

However, when run the app on the LG Nexus 5 it runs this part:

} else {
    Toast.makeText(this, "No NDEF messages found!", Toast.LENGTH_SHORT).show();

I have been told that it is most likely due to the tags we're using not being compatible with all devices. However, I thought it could also be something programmatically, since I am not experienced working with Android and NFC.

The tags are student IDs. A tag reader app identified one of them as

Upvotes: 2

Views: 534

Answers (2)

Martijn Coenen
Martijn Coenen

Reputation: 981

On top of what Michael said, you can check whether your device supports Mifare Classic with

PackageManager.hasSystemFeature("com.nxp.mifare");

Upvotes: 1

Michael Roland
Michael Roland

Reputation: 40849

The problem you are experiencing is a result of the NFC chipset in your device not being compatible with MIFARE Classic. Typically, only devices with an NFC chipset from NXP are capable of reading MIFARE Classic (NXP is the owner of the MIFARE technology).

MIFARE Classic uses the anti-collision and activation mechanism defined in ISO/IEC 14443 Type A (and also ISO/IEC 18092). Therefore, that part matches the way other contactless smartcards and NFC tags work. As a result, all (most!) Android NFC devices will detect such cards/tags. However, the communication protocol and framing deviates from that defined for other NFC tags and contactless smartcards. This non-standard protocol is not available on other chipsets than those by NXP and therefore, no data can be read from MIFARE Classic cards on devices with non-NXP NFC controllers.

The HTC One m8 contains NXP's PN544 NFC controller and can therefore discover your tag and read data from it. The LG Nexus 5 contains Broadcom's BCM20793 NFC controller and can therefore discover your tag but is unable to read data from it.

Upvotes: 1

Related Questions