NFC stands for “Near Field Communication” and, as the name implies, it enables short range communication between compatible devices. This requires at least one transmitting device, and another to receive the signal. NFC allows you to share small payloads of data between an NFC tag and an Android-powered device, or between two Android-powered devices.
I was developing an application in which I had to accept the data from a spinner and two edit text fields, combine the data and write it into NFC tag.
I followed these simple steps to write the data into NFC tag:
1) Declare an Intent Filter to announce to the system that it’s enabled to work on NFC.
2) Have a method that Android will call when NFC is detected.
3) Create a method to build a NDEF message.
4) Create a method to write the NDEF message.
________________________________________________________________________________________________________
Manifest :
<uses-feature
android:name=“android.hardware.nfc”
android:required=“false” />
<uses-permission android:name=“android.permission.NFC” />
________________________________________________________________________________________________________
package com.nanostuffs.nfc.activity;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.nanostuffs.nfc.R;
public class WriteActivity extends Activity {
private NfcAdapter adapter;
private PendingIntent pendingIntent;
private IntentFilter writeTagFilters[];
private Tag mytag;
private Context ctx;
private Button write;
private String writeTag;
private Spinner selectFarmer;
private EditText noOfBags;
private EditText fuel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.write);
initializeComponents();
}
private void initializeComponents() {
selectFarmer = (Spinner) findViewById(R.id.sel_farmer_spinner);
noOfBags = (EditText) findViewById(R.id.no_of_bags_edit);
fuel = (EditText) findViewById(R.id.fuel_litres_edit);
write = (Button) findViewById(R.id.write);
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_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[] { tagDetected };
}
________________________________________________________________________________________________________
With last 5 rows we create a IntentFilter, so we tell Android that our application is enabled to work on nfc tag (NfcAdapter.ACTION_TAG_DISCOVERED). We could register our app directly with a intentFilter in the Manifest. In this way we couldn’t lunch our Activity like a simple program, but Android will boot it when it detects a tag. In both ways, after detecting and deciding which app has to work on with the tag, Android will call the method onNewIntent and pass the object tag to the activity:
________________________________________________________________________________________________________
@Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Toast.makeText(this,
this.getString(R.string.ok_detection) + mytag.toString(),
Toast.LENGTH_SHORT).show();
}
}
________________________________________________________________________________________________________
So now we have the object tag and we have to build the function to create the NDEF message and to write it into the NFC tag.
________________________________________________________________________________________________________
private NdefRecord createRecord(String text)
throws UnsupportedEncodingException {
String lang = “en”;
byte[] textBytes = text.getBytes();
byte[] langBytes = lang.getBytes(“US-ASCII”);
int langLength = langBytes.length;
int textLength = textBytes.length;
byte[] payload = new byte[1 + langLength + textLength];
// set status byte (see NDEF spec for actual bits)
payload[0] = (byte) langLength;
// copy langbytes and textbytes into payload
System.arraycopy(langBytes, 0, payload, 1, langLength);
System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);
NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], payload);
return recordNFC;
}
private void write(String text, Tag tag) throws IOException,
FormatException {
NdefRecord[] records = { createRecord(text) };
NdefMessage message = new NdefMessage(records);
// Get an instance of Ndef for the tag.
Ndef ndef = Ndef.get(tag);
// Enable I/O
ndef.connect();
// Write the message
ndef.writeNdefMessage(message);
// Close the connection
ndef.close();
}
________________________________________________________________________________________________________
Now we have to check if the device supports the NFC feature and if it is enabled.If so ,write the data.
________________________________________________________________________________________________________
@Override
public void onResume() {
super.onResume();
writeModeOn();
}
private void writeModeOn() {
if (adapter != null) {
adapter.enableForegroundDispatch(this, pendingIntent,
writeTagFilters, null);
write.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
writeTag = selectFarmer.getSelectedItemId()+1005 + “~”
+ noOfBags.getText() + “~” + fuel.getText();
try {
if (mytag == null) {
Toast.makeText(ctx,
ctx.getString(R.string.error_detected),
Toast.LENGTH_LONG).show();
} else {
write(writeTag, mytag);
Toast.makeText(ctx,
ctx.getString(R.string.ok_writing),
Toast.LENGTH_LONG).show();
}
} catch (IOException e) {
Toast.makeText(ctx,
ctx.getString(R.string.error_writing),
Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (FormatException e) {
Toast.makeText(ctx,
ctx.getString(R.string.error_writing),
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
if (!adapter.isEnabled()) {
new AlertDialog.Builder(this)
.setPositiveButton(“Update Settings”,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0,int arg1) {
Intent setnfc = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
startActivity(setnfc);
}
})
.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
finish();
}
}).create().show();
}
} else {
Toast.makeText(getApplicationContext(),
“Sorry, No NFC Adapter found.”, Toast.LENGTH_SHORT).show();
}
}
________________________________________________________________________________________________________
If the user exits the application disable the NFC adapter.
________________________________________________________________________________________________________
@Override
public void onPause() {
super.onPause();
writeModeOff();
}
private void writeModeOff() {
if (adapter != null) {
adapter.disableForegroundDispatch(this);
}
}
}