I'm new to the NFC technology and thought of starting with reading and writing a tag. For the reading purpose I am using a MIRFARE 1K smart card and for writing I am using an NTAG203. All I want is to get the TagID in the reading process and send the TagID and datetime stamp to the NTAG203.
Issues:
My application is having difficulty in compiling. It keeps giving me Error generating final archive: Failed to create 'C:\Android WS\TabletApp\bin\TabletApp.apks': Access is denied error. I clean the project and restart Eclipse but in vain. It only goes away when I restart my laptop. Any suggestions for this?
When the application works, it still does not give me the ID. I scan my card/tag and the MainActivity(ScanningActivity here) loads again and again. The control does not go further than this. Any suggestions on how to work on it?
public class ScanningActivity extends Activity {
private NfcAdapter sNfcAdapter;
Locale locale = new Locale("en", "US");
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
boolean encodeInUtf8 = false;
Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
int utfBit = encodeInUtf8 ? 0 : (1 << 7);
char status = (char)(utfBit + langBytes.length);
static String bin2hex(byte[] data) {
return String.format("%0" + (data.length * 2) + "X", new BigInteger(1, data));
}
/* write to tag */
boolean writeNdefMessageToTag(NdefMessage message, Tag detectedTag) throws FormatException {
int size = message.toByteArray().length;
try {
Ndef ndef = Ndef.get(detectedTag);
if (ndef != null) {
ndef.connect();
if (!ndef.isWritable()) {
Toast.makeText(this, "Tag is read-only.", Toast.LENGTH_SHORT).show();
return false;
}
if (ndef.getMaxSize() < size) {
Toast.makeText(this,
"The data cannot be written since the tag capacity is" + ndef.getMaxSize() +
" bytes and the data to be transferred is " + size + " bytes",
Toast.LENGTH_LONG).show();
return false;
}
ndef.writeNdefMessage(message);
ndef.close();
Toast.makeText(this, "Data sent to the Tag", Toast.LENGTH_LONG).show();
return true;
} else {
NdefFormatable ndefFormat = NdefFormatable.get(detectedTag);
if (ndefFormat != null) {
try {
ndefFormat.connect();
ndefFormat.format(message);
ndefFormat.close();
Toast.makeText(this, "Data sent", Toast.LENGTH_LONG).show();
return true;
} catch (IOException e) {
Toast.makeText(this, "Unable to format tag", Toast.LENGTH_LONG).show();
return false;
}
} else {
Toast.makeText(this, "Not supported tag", Toast.LENGTH_LONG).show();
return false;
}
}
} catch (IOException e) {
Toast.makeText(this, "Sending failed", Toast.LENGTH_LONG).show();
}
return false;
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scanning);
TextView tg = (TextView)findViewById(R.id.tagid);
final TextView tvtime = (TextView)findViewById(R.id.datetime);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
String currentTimeStamp = dateFormat.format(new Date()); // Find todays date
tvtime.setText(currentTimeStamp);
sNfcAdapter = NfcAdapter.getDefaultAdapter(this);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
if (sNfcAdapter == null) {
Toast.makeText(this, "This device does not support NFC or you have not scanned the card properly",
Toast.LENGTH_LONG).show();
return;
}
if (!sNfcAdapter.isEnabled()) {
Toast.makeText(this, "Looks like the NFC is not enabled on your device", Toast.LENGTH_LONG).show();
new AlertDialog.Builder(this).setTitle("NFC disabled").setMessage(
"Looks like the NFC is not enabled on your device. Please enable it.").setPositiveButton(
"Ok", null).show();
}
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
try {
String TagID = tag.getId().toString();
tg.setText(bin2hex(tag.getId()));
Toast.makeText(getApplicationContext(), bin2hex(tag.getId()), Toast.LENGTH_LONG).show();
Toast.makeText(this, TagID, Toast.LENGTH_LONG).show();
} catch (Exception ex) {
new AlertDialog.Builder(this).setTitle("Error!").setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent(ScanningActivity.this, ScanningActivity.class);
startActivity(i);
}
}).setMessage(ex.getMessage() + "\n\nPlease click Ok. This will restart the application").create().show();
new AlertDialog.Builder(this).setTitle("Transferring the data").setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
TextView tvData = (TextView)findViewById(R.id.Data);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
Tag tag1 = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
String DataToSend = tvtime.getText().toString() + tag1.getId().toString();
//String DataToSend = "Data";
//tvData.setText(tvtime.getText().toString()+tag.getId().toString());
byte[] textBytes = DataToSend.getBytes(utfEncoding);
byte[] dataa = new byte[1 + langBytes.length + textBytes.length];
dataa[0] = (byte)status;
System.arraycopy(langBytes, 0, dataa, 1, langBytes.length);
System.arraycopy(textBytes, 0, dataa, 1 + langBytes.length, textBytes.length);;
NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], dataa);
NdefMessage newMessage = new NdefMessage(new NdefRecord[] { textRecord });
try {
writeNdefMessageToTag(newMessage, tag1);
} catch (FormatException e) {
e.printStackTrace();
}
}
}
}).setMessage(
"Place this tablet on the RFID Tag on the Microbiology Form. Keep it there until you get to the next screen").create().show();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.scanning, menu);
return true;
}
}
and the Manifest is
<uses-permission android:name="android.permission.NFC"/>
<uses-sdk
android:minSdkVersion="13"
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.tabletapp.ScanningActivity"
android:label="@string/app_name" >
<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="text/plain" />
</intent-filter>
</activity>
</application>
Update:
The app does not show any toast. When I put a card/tag on the device, I am asked which app will I like to use. I select the one we are talking about and the 'ScanningActivity' (MainActivity) loads again. Neither does not show me the ID nor does it go past the scanning activity.
I want to read the ID from a card and then write it, along with the timestamp, to another tag.