Conrad
Conrad

Reputation: 953

My NFC Reader cannot successfully read the right data

I have developed a simple NFC app which will launch after sensing the NFC tag. There are two questions I would like to ask, why after my program launch, I need to let the device to sense the tag again whether than it will just read the tag after it launch? And, I have set the data type to read as text/plain, but why when I output the data in a textview field, a meaningless query appear?

public class Reader extends Activity {

TextView mText;
NfcAdapter mAdapter;
PendingIntent mPendingIntent;
IntentFilter mFilters[];
String mTechLists[][];

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

@Override
public void onStart(){
    super.onStart();
    setContentView(R.layout.activity_reader);

    mText = (TextView) findViewById(R.id.text);

    mAdapter = NfcAdapter.getDefaultAdapter(this);
    mPendingIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    try{
        ndef.addDataType("text/plain");
    }catch(MalformedMimeTypeException e){
        throw new RuntimeException("fail", e);
    }

    IntentFilter nt = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
    mFilters = new IntentFilter[]{
            ndef, nt
    };

    mTechLists = new String[][]{
            new String[]{
                    Ndef.class.getName()
            }
    };
    Intent intent = getIntent();
    mText.setText(getNdefMessages(intent));
}

public String getNdefMessages(Intent intent){
    NdefMessage[] msgs = null;
    String action = intent.getAction();
    if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)||
            NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)){
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if(rawMsgs != null){
            msgs = new NdefMessage[rawMsgs.length];
            for(int i=0; i<rawMsgs.length; i++){
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        }else{
            byte[] empty = new byte[]{};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
            msgs = new NdefMessage[]{msg};
        }

    }
    if(msgs==null)
        return "No Tag discovered!";
    else
        return msgs.toString();
}

@Override
public void onResume(){
    super.onResume();
    if (mAdapter != null)
        mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);

}

@Override
public void onPause(){
    super.onPause();
    if (mAdapter != null)
        mAdapter.disableForegroundDispatch(this);
}

@Override
public void onNewIntent(Intent intent){
    Log.i("Foreground dispatch", "Discovered tag with intent:" + intent);
    mText = (TextView) findViewById(R.id.text);
    mText.setText(getNdefMessages(intent));
}

}

Above is my main program, and below is the Manifest file:

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

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

<uses-permission 
    android:name="android.permission.NFC"/>

<uses-feature 
    android:name="android.hardware.nfc"
    android:required="true"/>

<application android:label="@string/app_name"
    android:icon="@drawable/ic_launcher"
    android:theme="@style/AppTheme"
    android:debuggable="true">
    <activity 
        android:name=".Reader"
        android:label="@string/title_activity_reader">
        <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"/>
            <data android:mimeType="text/plain" /> 
            <!--<data 
                android:scheme="http"
                android:host="developer.android.com"/>-->
            <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>
    </activity>

</application>

</manifest>

Message shows in the app:

enter image description here

At last is the data I input into the tag:

enter image description here

Upvotes: 1

Views: 3569

Answers (1)

NFC guy
NFC guy

Reputation: 10228

An NdefMessage is an object that contains one or more NdefRecords. Call yourNdefMessage.getRecords() to access them.

An NdefRecord can have various types with accompanying content, including plain text. There are 2 types of plain text NdefRecords: Well-Known Type Text and MIME-type "text/plain" (both use the same intent filter; see http://developer.android.com/guide/topics/connectivity/nfc/nfc.html#ndef for details).

You seem to use the MIME-type text/plain. So you can easily convert it to a String: new String(yourNdefMessage.getRecords()[0].getPayload()).

To make sure your app can immediately access the tag when started you should put the Android Application Record as the last record in the NDEF message. Otherwise the generated intent will contain the action MAIN instead of NDEF_DISCOVERED and there will be no NDEF message and TAG EXTRAs in the intent.

Upvotes: 2

Related Questions