Search code examples
androidandroid-studionfcreader

How to get plain text from NFC Tag?


I have tried to implement the code from Google documentation but it is still not clear for me. What am I missing here?

This is method in MainActivity.java:

    @Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        Parcelable[] rawMessages =
                intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMessages != null) {
            NdefMessage[] messages = new NdefMessage[rawMessages.length];
            for (int i = 0; i < rawMessages.length; i++) {
                messages[i] = (NdefMessage) rawMessages[i];
                Log.i("nfcccc",messages[i].toString());
            }
            // Process the messages array.
            Log.i("from tag: ",messages.toString());
            Toast.makeText(this,messages.toString(),Toast.LENGTH_LONG).show();

        }
    }
}

In onCreated method I have also initialized nfcAdapter:

        nfcAdapter = NfcAdapter.getDefaultAdapter(this);

In manifest file I have this:

<activity android:name=".MainActivity">

        <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.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>



    </activity>

I spent couple of days trying to implement that, but it is still not working. What I am doing is that I use NFC Tools android app to save plain text and the I want to read this data in my own app>


Solution

  • What you are missing is the interaction with the Activity's launch mode as NFC handling is done by another System App and then with what Google document as how to use NFC it is just like your application is receiving data from another App.

    So onNewIntent

    This is called for activities that set launchMode to "singleTop" in their package

    https://developer.android.com/reference/android/app/Activity#onNewIntent(android.content.Intent)

    Your application will have launchMode as standard as default therefore onNewIntent is never called

    There are 2 standard parts for using the old NFC API's with Intents

    1. Activity is not running (which usually means the App Task is not running), set manifest filters in Activity and then in oncreate use getIntent and then process the Intent for being an NFC based Intent (as per you would do on onNewIntent)

    2. Activity (and App) is running and in the foreground, enableForegroundDispatch https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc#foreground-dispatch which basically tells the NFC system app to restart this Activity when it is the "Top" activity as though it was a "singleTop" Activity, then onNewIntent is called by the incoming Intent (This has a negative side effect of Pausing and Resuming your Activity)

    Note there are different ways to setup launchMode and what Activity is top of the stack to get it to tie up sending the Intent to onNewIntent but they are less common.
    Best to handle NFC Intents in onCreate and alsoenableForegroundDispatch with the same handling in onNewIntent

    An even better way to get more control is use the newer and better enableReaderMode API https://developer.android.com/reference/android/nfc/NfcAdapter#enableReaderMode(android.app.Activity,%20android.nfc.NfcAdapter.ReaderCallback,%20int,%20android.os.Bundle)

    Summary So just add the code for foregroundDispatch as per https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc#foreground-dispatch