0

The main problem is that we are unable to go to onNewIntent() when i tap my phone with other NFC enabled phone(NFC is ON). Under no circumstances other than the main intent, i am unable to reach onNewIntent. I have tried all the three filters NDEF,TECH, TAG.

package com.example.nfctry;

import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
NfcAdapter adapter;
PendingIntent pendingIntent;
IntentFilter writeTagFilters[];
boolean writeMode;
Tag myTag;
Context ctx;



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

    ctx = this;

    adapter = NfcAdapter.getDefaultAdapter(this);
    pendingIntent = PendingIntent.getActivity(this,0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0);
    IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
    tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
    writeTagFilters = new IntentFilter[] {tagDetected};

    onNewIntent(getIntent());



}

@Override
protected void onNewIntent(Intent intent)
{
    Toast.makeText(this,""+intent.getAction(), Toast.LENGTH_LONG).show();
    super.onNewIntent(intent);
    // getIntent() should always return the most recent
    if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
    {
        myTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        Toast.makeText(this,"DETECTED muahhhhh"  + myTag.toString(), Toast.LENGTH_LONG).show();

    }


}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

and in android mainfest i have added the intentfilters as well.

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfctry"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="15"
    android:targetSdkVersion="17" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.nfctry.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <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.TAG_DISCOVERED" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

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

1 Answers1

3

It's indepent off which TAG filter you use. Your onNewIntent only get's called when an intent is called using the launchMode: singleTop or singleTask and ofcourse when you call it yourself. When your application is in the front it doesn't catch the NDEF/TECH/TAG discovery. You need to use ForegroundDispatching to catch the tag discovery events in your current app.

When your ForegroundDispatch catch the event and you use PendingIntent.getActivity with the flag FLAG_ACTIVITY_SINGLE_TOP in your PendingIntent it will call onNewIntent.

You should enable the ForegroundDispatch in onResume:

@Override
public void onResume()
{
    super.onResume();

    PendingIntent pendingIntent     = PendingIntent.getActivity(this,0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0);     
    IntentFilter[] intentFilters    = { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED) };      

    adapter.enableForegroundDispatch(   this,
            pendingIntent, 
            intentFilters,
            new String[][]{
            new String[]{"android.nfc.tech.NfcA"}
        });     
}

And disable it in onPause:

@Override
public void onPause() {
    super.onPause();

    if (adapter != null) 
    {
        try {
            adapter.disableForegroundDispatch(this);
        } 
        catch (NullPointerException e) {
        }
    }
}  

To catch the TAG event in your current code with ForegroundDispatch it will be something like this:

public class MainActivity extends Activity {

    NfcAdapter adapter;
    PendingIntent pendingIntent;
    IntentFilter writeTagFilters[];
    boolean writeMode;
    Tag myTag;
    Context ctx;    

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

        ctx = this;
        adapter = NfcAdapter.getDefaultAdapter(this);
        onNewIntent(this.getIntent());      
    }


    @Override
    public void onNewIntent(Intent data) 
    {
        Toast.makeText(this,""+intent.getAction(), Toast.LENGTH_LONG).show();
        super.onNewIntent(intent);
        // getIntent() should always return the most recent
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
        {
            myTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Toast.makeText(this,"DETECTED muahhhhh"  + myTag.toString(), Toast.LENGTH_LONG).show();

        }
    }   

    @Override
    public void onResume()
    {
        super.onResume();

        PendingIntent pendingIntent     = PendingIntent.getActivity(this,0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0);     
        IntentFilter[] intentFilters    = { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED) };      

        adapter.enableForegroundDispatch(   this,
                pendingIntent, 
                intentFilters,
                new String[][]{
                new String[]{"android.nfc.tech.NfcA"}
            });     
    }

    @Override
    public void onPause() {
        super.onPause();

        if (adapter != null) 
        {
            try {
                adapter.disableForegroundDispatch(this);
            } 
            catch (NullPointerException e) {
            }
        }
    }    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

Also note that you should add the NFC user permissions in your manifest.

S.Pols
  • 3,414
  • 2
  • 21
  • 42
  • thanks, i got the error. but now whenever i am trying to fetch the ID, everytime i am getting a different ID. NdefMessage[] msgs = getTechMessages(getIntent()); NdefRecord record = msgs[0].getRecords()[0]; byte[] payload = record.getId(); – Soumabha Roy Chaudhuri Aug 25 '14 at 08:42
  • payload is giving "null", whereas getID() is givng some random values of sort "[B@426fd2a0". We dont have data in our nfc tag, the main aim is just to fetch a unique ID. – Soumabha Roy Chaudhuri Aug 25 '14 at 09:07
  • `[B@426fd2a0` is not the real ASCII output. You should print it with `new String(payload)`. – S.Pols Aug 25 '14 at 09:13
  • You should't also get the ID of the NDEF record because it doesn't return the ID of the device. You should use `myTag.getId()`. If you use HCE at the other side also note that the UID is different every transaction. It's randomly generated each transaction. – S.Pols Aug 25 '14 at 09:28