user1697760
user1697760

Reputation: 33

Getting NFC Unique ID within the oncreate method

I am trying to get the unique ID of a NFC tag within the on create method. I have done this successfully using an override method called "onNewIntent" however i want to get it within the oncreate method. Here is what i have tried, the application on my phone crashes when starting up. Please can anyone help. Thanks.

public class MainActivity extends Activity {

    TextView uid;

    private final String[][] techList = new String[][] {
        new String[] {
            NfcA.class.getName(),
            NfcB.class.getName(),
            NfcF.class.getName(),
            NfcV.class.getName(),
            NdefFormatable.class.getName(),
            TagTechnology.class.getName(),
            IsoDep.class.getName(),
            MifareClassic.class.getName(),
            MifareUltralight.class.getName(), 
            Ndef.class.getName()
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        uid = (TextView) findViewById(R.id.UID);
        Intent i = new Intent();
        IntentFilter filter = new IntentFilter();
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        filter.addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]{filter}, this.techList);
        if (i.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED)) {
            ((TextView)findViewById(R.id.UID)).setText(ByteArrayToHexString(i.getByteArrayExtra(NfcAdapter.EXTRA_ID)));
        }
    }

    private String ByteArrayToHexString(byte [] inarray) { //converts byte arrays to string
        int i, j, in;
        String [] hex = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
        String out= "";

        for(j = 0 ; j < inarray.length ; ++j) 
            {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
            }
        return out;
    }
}

Upvotes: 2

Views: 2202

Answers (2)

Michael Roland
Michael Roland

Reputation: 40831

You seem to be mixing two concepts here: NFC intents registered in the app manifest and foreground dispatch.

Automatically starting an app based on NFC events:

This mechanism requires you to register intent filters in your app manifest, e.g.

<activity ...>
    <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" />
</activity>

Then your activity will be automatically started upon tag detection. (NOTE: Avoid using the TAG_DISCOVERED intent for this type of dispatch as that intent (when used in the manifest) is meant as a fall-back only!)

Now, if your app is started, you can detect if it was started by the TECH_DISCOVERED intent in your onCreate() method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    uid = (TextView) findViewById(R.id.UID);

    Intent i = getIntent();  // get the intent that started us
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(i.getAction())) {
        uid.setText(ByteArrayToHexString(i.getByteArrayExtra(NfcAdapter.EXTRA_ID)));
    }
}

Foreground dispatch system:

The foreground dispatch system is used to register your current foreground activity to be notified about (and to get highest priority for receiving) NFC events. You use it by registering for the relevant intent (TAG_DISCOVERED is fine in that case) with the enableForegroundDispatch() method. Upon receiving an NFC event, your activity is notified through onNewIntent().

Keep in mind, however, that you are only allowed to register for the foreground dispatch while your activity is the foreground activity (i.e. you must register in onResume() and must deregister in onPause()), otherwise your app will block NFC events or crash (depending on the Android version). So never use enableForegroundDispatch() in onCreate().

Upvotes: 0

ozbek
ozbek

Reputation: 21183

Ok so basically i create a new intent. I get the default NFC hardware from the device. If a tag is discovered, it should change the textview to the ID of the NFC tag

To achieve that, all you have to do is to set the new text and call invalidate() in onNewIntent() so that that TextView would be re-drawn with the new text:

package com.example.changetext;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    private TextView mNfcAdapterUid;

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

        mNfcAdapterUid = (TextView)findViewById(R.id.nfc_adapter_uid);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            mNfcAdapterUid.setText(ByteArrayToHexString(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)));
            mNfcAdapterUid.invalidate();
        }
    }

    private String ByteArrayToHexString(byte[] inarray) { // converts byte arrays to string
        int i, j, in;
        String[] hex = {
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
        };
        String out = "";

        for (j = 0; j < inarray.length; ++j) {
            in = inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }
}

Hope this helps.

Upvotes: 3

Related Questions