When app receives NFC data it opens "New Tag collected"

3.8k views Asked by At

I am creating an app where two devices communicate over NFC and then one transmits to the server.

I am trying to develop this for both pre- and post-lollipop. The problem is that I create my NDEF message in one app and then receive it in another app. However when I try to receive in the other app, the NFC "New Tag collected" screen is opened instead of my app. This is a real problem for me, I'm just sending a string which I need to send to a web service.

Below is the manifest of the receiving application:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.devcompany.paymentcustomer" >
    <uses-permission android:name="android.permission.NFC" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".activities.HomeActivity"
            android:launchMode="singleTop"
            android:label="@string/app_name"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />

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

</manifest>

Here is my code for sending:

   mNfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());


        //If device is running lollipop remove the touch to beam action
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    mNfcAdapter.setNdefPushMessageCallback(nDefCallback, getActivity());
                    mNfcAdapter.invokeBeam(getActivity());
                }

            }, 2000);
        }else{
            //leave touch to beam action
            mNfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
                @Override
                public NdefMessage createNdefMessage(NfcEvent event) {
                    NdefMessage message = new NdefMessage((new NdefRecord[]{createMime("application/com.devcompany.paymentvendor.fragments", mToBeam.getBytes()) }));

                    return message;
                }
            }, getActivity());

            mNfcAdapter.setOnNdefPushCompleteCallback(
                    new NfcAdapter.OnNdefPushCompleteCallback() {

                        @Override
                        public void onNdefPushComplete(NfcEvent event) {

                        }
                    }, getActivity());
        }

Here is my code for receiving:

public class HomeActivity extends ActionBarActivity {

    private NfcAdapter mAdapter;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_layout);

        mAdapter = NfcAdapter.getDefaultAdapter(this);
        textView = (TextView)findViewById(R.id.fortressLabel);

    }

    @Override
    public void onResume(){
        super.onResume();
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())){
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    private void processIntent(Intent intent){

        //textView.setText(intent.getDataString());
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];

        Log.i(this.getLocalClassName(), intent.getDataString());
    }
}

I have debugged my receiving code and stepped through it, when I hold the phones together, the code doesn't even enter the onResume method. The tags intent is launched first. I don't understand why this is happening. Can anyone help me on this one?

1

There are 1 answers

0
Michael Roland On BEST ANSWER

You are sending a MIME type record of type "application/com.devcompany.paymentvendor.fragments":

NdefMessage message = new NdefMessage(new NdefRecord[] {
    NdefRecord.createMime("application/com.devcompany.paymentvendor.fragments",
                  mToBeam.getBytes())
});

Consequently, you also need to instruct your receiving activity to actually receive that MIME type record. You can register your app to open (and receive) upon detection of that MIME type in an NFC event by adding an NDEF_DISCOVERED intent filter for your activity:

<activity android:name=".activities.HomeActivity" ...>
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/com.devcompany.paymentvendor.fragments" />
    </intent-filter>
</activity>