() {
- public DesfireFileSettings createFromParcel(Parcel source) {
- byte fileType = source.readByte();
- byte commSetting = source.readByte();
- byte[] accessRights = new byte[source.readInt()];
- source.readByteArray(accessRights);
-
- if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE) {
- int fileSize = source.readInt();
- return new StandardDesfireFileSettings(fileType, commSetting, accessRights, fileSize);
- } else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE) {
- int recordSize = source.readInt();
- int maxRecords = source.readInt();
- int curRecords = source.readInt();
- return new RecordDesfireFileSettings(fileType, commSetting, accessRights, recordSize, maxRecords, curRecords);
- } else {
- return new UnsupportedDesfireFileSettings(fileType);
- }
- }
-
- public DesfireFileSettings[] newArray(int size) {
- return new DesfireFileSettings[size];
- }
- };
-
- public void writeToParcel (Parcel parcel, int flags) {
- parcel.writeByte(fileType);
- parcel.writeByte(commSetting);
- parcel.writeInt(accessRights.length);
- parcel.writeByteArray(accessRights);
- }
-
- public int describeContents () {
- return 0;
- }
-
- public static class StandardDesfireFileSettings extends DesfireFileSettings {
- public final int fileSize;
-
- private StandardDesfireFileSettings (ByteArrayInputStream is) throws IOException {
- super(is);
-
- fileSize = readReverseUnsigned3(is);
- }
-
- StandardDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int fileSize) {
- super(fileType, commSetting, accessRights);
- this.fileSize = fileSize;
- }
-
- @Override
- public void writeToParcel (Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeInt(fileSize);
- }
- }
-
- public static class RecordDesfireFileSettings extends DesfireFileSettings {
- public final int recordSize;
- public final int maxRecords;
- public final int curRecords;
-
- public RecordDesfireFileSettings(ByteArrayInputStream is) throws IOException {
- super(is);
-
- recordSize = readReverseUnsigned3(is);
- maxRecords = readReverseUnsigned3(is);
- curRecords = readReverseUnsigned3(is);
- }
-
- RecordDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int recordSize, int maxRecords, int curRecords) {
- super(fileType, commSetting, accessRights);
- this.recordSize = recordSize;
- this.maxRecords = maxRecords;
- this.curRecords = curRecords;
- }
-
- @Override
- public void writeToParcel (Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeInt(recordSize);
- parcel.writeInt(maxRecords);
- parcel.writeInt(curRecords);
- }
- }
-
- public static class UnsupportedDesfireFileSettings extends DesfireFileSettings {
- public UnsupportedDesfireFileSettings(byte fileType) {
- super(fileType, Byte.MIN_VALUE, new byte[0]);
- }
- }
-
- public int readAccessKey() {
- return (accessRights[0] & 0xF0) >> 4;
- }
-
- public int writeAccessKey() {
- return accessRights[0] & 0x0F;
- }
-
- public int readWriteAccessKey() {
- return (accessRights[1] & 0xF0) >> 4;
- }
-
- public int changeAccessKey() {
- return accessRights[1] & 0x0F;
- }
-
- public boolean freeReadAccess() {
- return readAccessKey() == 0xE || readWriteAccessKey() == 0xE;
- }
-
- public boolean freeWriteAccess() {
- return writeAccessKey() == 0xE || readWriteAccessKey() == 0xE;
- }
-
- public byte[] getAccessRights() {
- return accessRights;
- }
-
- public static class ValueDesfireFileSettings extends DesfireFileSettings {
- public final long lowerLimit;
- public final long upperLimit;
- public final long limitedCreditValue;
- public final byte limitedCreditEnabled;
-
- public ValueDesfireFileSettings(ByteArrayInputStream is) throws IOException {
- super(is);
-
- lowerLimit = readUnsigned4Reverse(is);
- upperLimit = readUnsigned4Reverse(is);
- limitedCreditValue = readUnsigned4Reverse(is);
-
- limitedCreditEnabled = (byte)is.read();
- }
-
- public ValueDesfireFileSettings(byte fileType, byte commSetting, byte[] accessRights, long lowerLimit, long upperLimit, long limitedCreditValue, byte limitedCreditEnabled) {
- super(fileType, commSetting, accessRights);
- this.lowerLimit = lowerLimit;
- this.upperLimit = upperLimit;
- this.limitedCreditValue = limitedCreditValue;
- this.limitedCreditEnabled = limitedCreditEnabled;
- }
-
- @Override
- public void writeToParcel (Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeLong(lowerLimit);
- parcel.writeLong(upperLimit);
- parcel.writeLong(limitedCreditValue);
- parcel.writeByte(limitedCreditEnabled);
- }
- }
-
- private static long readUnsigned4Reverse(InputStream in) throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- int ch3 = in.read();
- int ch4 = in.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((long)(ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
- }
-
- private static int readReverseUnsigned3(InputStream in) throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- int ch3 = in.read();
- if ((ch1 | ch2 | ch3) < 0)
- throw new EOFException();
- return (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
- }
-}
diff --git a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/DesfireReader.java b/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/DesfireReader.java
deleted file mode 100644
index 1b37ca0..0000000
--- a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/DesfireReader.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.desfire.nfc;
-
-import java.io.ByteArrayOutputStream;
-
-import android.nfc.tech.IsoDep;
-import android.util.Log;
-
-public class DesfireReader {
-
- private static final String TAG = DesfireReader.class.getName();
-
- /* Commands */
- public static final byte GET_VERSION_INFO = (byte) 0x60;
- public static final byte GET_APPLICATION_DIRECTORY = (byte) 0x6A;
- public static final byte GET_ADDITIONAL_FRAME = (byte) 0xAF;
- public static final byte SELECT_APPLICATION = (byte) 0x5A;
- public static final byte READ_DATA = (byte) 0xBD;
- public static final byte READ_RECORD = (byte) 0xBB;
- public static final byte GET_FILES = (byte) 0x6F;
- public static final byte GET_FILE_SETTINGS = (byte) 0xF5;
-
- public static final byte INIT_AUTH = (byte) 0x0a;
- public static final byte FINISH_AUTH = (byte) 0xAF;
-
- public static final byte GET_KEY_VERSION = (byte) 0x64;
-
- public static final byte CREATE_APPLICATION = (byte) 0xCA; // {6 bytes: cmd, , , , uint8 settings, uint8 keyNo}
- public static final byte DELETE_APPLICATION = (byte) 0xDA; // {4 bytes: }
-
- /* Status codes */
- public static final byte STATUS_OPERATION_OK = (byte)0x00;
- public static final byte STATUS_PERMISSION_ERROR = (byte)0x9D;
- public static final byte STATUS_ADDITIONAL_FRAME = (byte)0xAF;
-
- private IsoDep isoDep;
-
- public DesfireReader(IsoDep isoDep) {
- this.isoDep = isoDep;
- }
-
- public int[] getApplicationDirectory() throws Exception {
- byte[] apps = sendRequest(GET_APPLICATION_DIRECTORY);
-
- int[] appIds = new int[apps.length / 3];
-
- for (int app = 0; app < apps.length; app += 3) {
- appIds[app / 3] = ((apps[app] & 0xFF) << 16) + ((apps[app + 1] & 0xFF) << 8) + (apps[app + 2] & 0xFF);;
- }
-
- return appIds;
- }
-
- public void selectApplication(int appId) throws Exception {
- byte[] buffer = new byte[3];
- buffer[0] = (byte) ((appId & 0xFF0000) >> 16);
- buffer[1] = (byte) ((appId & 0xFF00) >> 8);
- buffer[2] = (byte) (appId & 0xFF);
-
- sendRequest(SELECT_APPLICATION, buffer);
- }
-
- public int[] getFiles() throws Exception {
- byte[] buf = sendRequest(GET_FILES);
- int[] fileIds = new int[buf.length];
- for (int x = 0; x < buf.length; x++) {
- fileIds[x] = (int)buf[x];
- }
- return fileIds;
- }
-
- public DesfireFileSettings getFileSettings (int fileNo) throws Exception {
- byte[] data = sendRequest(GET_FILE_SETTINGS, new byte[] { (byte) fileNo });
- return DesfireFileSettings.Create(data);
- }
-
- public byte[] readFile (int fileNo) throws Exception {
- return sendRequest(READ_DATA, new byte[] {
- (byte) fileNo,
- (byte) 0x0, (byte) 0x0, (byte) 0x0,
- (byte) 0x0, (byte) 0x0, (byte) 0x0
- });
- }
-
- public byte[] readRecord (int fileNum) throws Exception {
- return sendRequest(READ_RECORD, new byte[]{
- (byte) fileNum,
- (byte) 0x0, (byte) 0x0, (byte) 0x0,
- (byte) 0x0, (byte) 0x0, (byte) 0x0
- });
- }
-
- private byte[] sendRequest (byte command) throws Exception {
- return sendRequest(command, null);
- }
-
- public VersionInfo getVersionInfo() throws Exception {
- byte[] bytes = sendRequest(GET_VERSION_INFO);
-
- return new VersionInfo(bytes);
- }
-
- private byte[] sendRequest (byte command, byte[] parameters) throws Exception {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
-
- byte[] recvBuffer = isoDep.transceive(wrapCommand(command, parameters));
-
- while (true) {
- if (recvBuffer[recvBuffer.length - 2] != (byte) 0x91) {
- throw new Exception("Invalid response");
- }
-
- output.write(recvBuffer, 0, recvBuffer.length - 2);
-
- byte status = recvBuffer[recvBuffer.length - 1];
- if (status == STATUS_OPERATION_OK) {
- break;
- } else if (status == STATUS_ADDITIONAL_FRAME) {
- recvBuffer = isoDep.transceive(wrapCommand(GET_ADDITIONAL_FRAME, null));
- } else if (status == STATUS_PERMISSION_ERROR) {
- throw new DesfireException(status, "Permission denied");
- } else {
- throw new DesfireException(status, "Unknown status code: " + Integer.toHexString(status & 0xFF));
- }
- }
-
- return output.toByteArray();
- }
-
- private byte[] wrapCommand(byte command, byte[] parameters) throws Exception {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
-
- stream.write(0x90);
- stream.write(command);
- stream.write(0x00);
- stream.write(0x00);
- if (parameters != null) {
- stream.write(parameters.length);
- stream.write(parameters);
- }
- stream.write(0x00);
-
- return stream.toByteArray();
- }
-
-}
diff --git a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/MainActivity.java b/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/MainActivity.java
deleted file mode 100644
index 38a2606..0000000
--- a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/MainActivity.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package com.desfire.nfc;
-
-import java.io.IOException;
-
-import org.ndeftools.util.activity.NfcDetectorActivity;
-
-import android.content.Intent;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.tech.IsoDep;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Gravity;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class MainActivity extends NfcDetectorActivity {
-
- private static final String TAG = MainActivity.class.getName();
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- setDetecting(true);
- }
-
- /**
- *
- * NFC feature was found and is currently enabled
- *
- */
-
- @Override
- protected void onNfcStateEnabled() {
- toast(getString(R.string.nfcAvailableEnabled));
- }
-
- /**
- *
- * NFC feature was found but is currently disabled
- *
- */
-
- @Override
- protected void onNfcStateDisabled() {
- toast(getString(R.string.nfcAvailableDisabled));
- }
-
- /**
- *
- * NFC setting changed since last check. For example, the user enabled NFC in the wireless settings.
- *
- */
-
- @Override
- protected void onNfcStateChange(boolean enabled) {
- if(enabled) {
- toast(getString(R.string.nfcAvailableEnabled));
- } else {
- toast(getString(R.string.nfcAvailableDisabled));
- }
- }
-
- /**
- *
- * This device does not have NFC hardware
- *
- */
-
- @Override
- protected void onNfcFeatureNotFound() {
- toast(getString(R.string.noNfcMessage));
- }
-
- @Override
- protected void nfcIntentDetected(Intent intent, String action) {
- Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- if(tag != null) {
-
- IsoDep isoDep = null;
-
- String[] techList = tag.getTechList();
- for (String tech : techList) {
- Log.d(TAG, "Tech " + tech);
-
- if (tech.equals(android.nfc.tech.IsoDep.class.getName())) {
- isoDep = android.nfc.tech.IsoDep.get(tag);
- }
- }
-
- if(isoDep != null) {
- Log.d(TAG, "Detected Desfire tag");
-
- TextView textView = (TextView) findViewById(R.id.title);
- textView.setText("Desfire tag!");
-
- try {
- isoDep.connect();
-
- DesfireReader reader = new DesfireReader(isoDep);
-
- VersionInfo versionInfo = reader.getVersionInfo();
-
- Log.d(TAG, "UID " + toHexString(versionInfo.getUid()));
-
- Log.d(TAG, "Hardware version " + versionInfo.getHardwareVersion() + ", software version " + versionInfo.getSoftwareVersion());
- Log.d(TAG, "Hardware capacity " + versionInfo.getHardwareStorageSize() + ", software capacity " + versionInfo.getSoftwareStorageSize());
-
- int[] applicationDirectory = reader.getApplicationDirectory();
-
- Log.d(TAG, "Read " + applicationDirectory.length + " apps");
-
- for (int i = 0; i < applicationDirectory.length; i++) {
- reader.selectApplication(applicationDirectory[i]);
-
- int[] fileList = reader.getFiles();
-
- Log.d(TAG, "App " + Integer.toHexString(applicationDirectory[i]) + " at index " + i + " has " + fileList.length + " files");
-
-
- for (int k = 0; k < fileList.length; k++) {
- DesfireFileSettings fileSettings = reader.getFileSettings(fileList[k]);
-
- Log.d(TAG, "Read file " + k + " settings " + fileSettings.getClass().getSimpleName() + " 0x" + Integer.toHexString(fileList[k]) + " " + fileSettings.getFileTypeName());
-
- // print file access
- if(fileSettings.freeReadAccess()) {
- Log.d(TAG, "File " + k + " is readable");
- }
- if(fileSettings.freeWriteAccess()) {
- Log.d(TAG, "File " + k + " is writable");
- }
-
- byte[] fileContents = reader.readFile(fileList[k]);
-
- Log.d(TAG, "Read " + fileContents.length + " bytes for file "+ k);
- }
- }
-
- } catch (Exception e) {
- Log.d(TAG, "Problem accessing Desfire tag", e);
- } finally {
- try {
- isoDep.close();
- } catch (IOException e) {
- // ignore
- }
- }
- } else {
- Log.d(TAG, "Did not detect a Desfire tag");
-
- TextView textView = (TextView) findViewById(R.id.title);
- textView.setText("Unknown tag!");
- }
- } else {
- Log.d(TAG, "No tag");
- }
-
- }
-
- public void toast(String message) {
- Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG);
- toast.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL, 0, 0);
- toast.show();
- }
-
- /**
- * Converts the byte array to HEX string.
- *
- * @param buffer
- * the buffer.
- * @return the HEX string.
- */
- public String toHexString(byte[] buffer) {
- StringBuilder sb = new StringBuilder();
- for(byte b: buffer)
- sb.append(String.format("%02x ", b&0xff));
- return sb.toString().toUpperCase();
- }
-
-
-}
diff --git a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/VersionInfo.java b/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/VersionInfo.java
deleted file mode 100644
index c7206d7..0000000
--- a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/com/desfire/nfc/VersionInfo.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package com.desfire.nfc;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-
-// https://code.google.com/p/nfc-tools/source/browse/trunk/libfreefare/examples/mifare-desfire-info.c?r=751
-
-public class VersionInfo {
-
- private int hardwareVendorId;
- private int hardwareType;
- private int hardwareSubtype;
- private int hardwareVersionMajor;
- private int hardwareVersionMinor;
- private int hardwareStorageSize;
- private int hardwareProtocol;
-
- private int softwareVendorId;
- private int softwareType;
- private int softwareSubtype;
- private int softwareVersionMajor;
- private int softwareVersionMinor;
- private int softwareStorageSize;
- private int softwareProtocol;
-
- byte[] uid = new byte[7]; // [7];
- byte[] batchNumber = new byte[5]; //[5];
- private int productionWeek;
- private int productionYear;
-
- public VersionInfo(byte[] bytes) throws IOException {
-
- DataInputStream din = new DataInputStream(new ByteArrayInputStream(bytes));
-
- hardwareVendorId = din.read();
- hardwareType = din.read();
- hardwareSubtype = din.read();
- hardwareVersionMajor = din.read();
- hardwareVersionMinor = din.read();
- hardwareStorageSize = din.read();
- hardwareProtocol = din.read();
-
- softwareVendorId = din.read();
- softwareType = din.read();
- softwareSubtype = din.read();
- softwareVersionMajor = din.read();
- softwareVersionMinor = din.read();
- softwareStorageSize = din.read();
- softwareProtocol = din.read();
-
- din.readFully(uid);
- din.readFully(batchNumber);
-
- productionWeek = din.read();
- productionYear = din.read();
- }
-
- public String getHardwareVersion() {
- return hardwareVersionMajor + "." + hardwareVersionMinor;
- }
-
- public String getSoftwareVersion() {
- return softwareVersionMajor + "." + softwareVersionMinor;
- }
-
- public int getHardwareVendorId() {
- return hardwareVendorId;
- }
-
- public void setHardwareVendorId(int hardwareVendorId) {
- this.hardwareVendorId = hardwareVendorId;
- }
-
- public int getHardwareType() {
- return hardwareType;
- }
-
- public void setHardwareType(int hardwareType) {
- this.hardwareType = hardwareType;
- }
-
- public int getHardwareSubtype() {
- return hardwareSubtype;
- }
-
- public void setHardwareSubtype(int hardwareSubtype) {
- this.hardwareSubtype = hardwareSubtype;
- }
-
- public int getHardwareVersionMajor() {
- return hardwareVersionMajor;
- }
-
- public void setHardwareVersionMajor(int hardwareVersionMajor) {
- this.hardwareVersionMajor = hardwareVersionMajor;
- }
-
- public int getHardwareVersionMinor() {
- return hardwareVersionMinor;
- }
-
- public void setHardwareVersionMinor(int hardwareVersionMinor) {
- this.hardwareVersionMinor = hardwareVersionMinor;
- }
-
- public int getHardwareStorageSize() {
- if((hardwareStorageSize & 1) > 0) {
- // >
- } else {
- // =
- }
-
- return (int)Math.pow (2, hardwareStorageSize >> 1);
-
- //return String.format("%s%d", ((hardwareStorageSize & 1) > 0 ? ">" : "="), (int)pow (2, hardwareStorageSize >> 1));
- }
-
- public void setHardwareStorageSize(int hardwareStorageSize) {
- this.hardwareStorageSize = hardwareStorageSize;
- }
-
- public int getHardwareProtocol() {
- return hardwareProtocol;
- }
-
- public void setHardwareProtocol(int hardwareProtocol) {
- this.hardwareProtocol = hardwareProtocol;
- }
-
- public int getSoftwareVendorId() {
- return softwareVendorId;
- }
-
- public void setSoftwareVendorId(int softwareVendorId) {
- this.softwareVendorId = softwareVendorId;
- }
-
- public int getSoftwareType() {
- return softwareType;
- }
-
- public void setSoftwareType(int softwareType) {
- this.softwareType = softwareType;
- }
-
- public int getSoftwareSubtype() {
- return softwareSubtype;
- }
-
- public void setSoftwareSubtype(int softwareSubtype) {
- this.softwareSubtype = softwareSubtype;
- }
-
- public int getSoftwareVersionMajor() {
- return softwareVersionMajor;
- }
-
- public void setSoftwareVersionMajor(int softwareVersionMajor) {
- this.softwareVersionMajor = softwareVersionMajor;
- }
-
- public int getSoftwareVersionMinor() {
- return softwareVersionMinor;
- }
-
- public void setSoftwareVersionMinor(int softwareVersionMinor) {
- this.softwareVersionMinor = softwareVersionMinor;
- }
-
- public int getSoftwareStorageSize() {
- return (int)Math.pow (2, softwareStorageSize >> 1);
- }
-
- public void setSoftwareStorageSize(int softwareStorageSize) {
- this.softwareStorageSize = softwareStorageSize;
- }
-
- public int getSoftwareProtocol() {
- return softwareProtocol;
- }
-
- public void setSoftwareProtocol(int softwareProtocol) {
- this.softwareProtocol = softwareProtocol;
- }
-
- public byte[] getUid() {
- return uid;
- }
-
- public void setUid(byte[] uid) {
- this.uid = uid;
- }
-
- public byte[] getBatchNumber() {
- return batchNumber;
- }
-
- public void setBatchNumber(byte[] batchNumber) {
- this.batchNumber = batchNumber;
- }
-
- public int getProductionWeek() {
- return productionWeek;
- }
-
- public void setProductionWeek(int productionWeek) {
- this.productionWeek = productionWeek;
- }
-
- public int getProductionYear() {
- return productionYear;
- }
-
- public void setProductionYear(int productionYear) {
- this.productionYear = productionYear;
- }
-
-
-}
diff --git a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/org/ndeftools/util/activity/NfcDetectorActivity.java b/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/org/ndeftools/util/activity/NfcDetectorActivity.java
deleted file mode 100644
index 390c61b..0000000
--- a/Android/Near Field Communications/HelloWorldNFC Desfire Solution/src/org/ndeftools/util/activity/NfcDetectorActivity.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/***************************************************************************
- *
- * This file is part of the 'NDEF Tools for Android' project at
- * http://code.google.com/p/ndef-tools-for-android/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ****************************************************************************/
-
-package org.ndeftools.util.activity;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.nfc.NfcAdapter;
-import android.os.Bundle;
-import android.util.Log;
-
-
-/**
- *
- * Abstract {@link Activity} for detecting incoming NFC messages.
- *
- * - detects whether NFC is available (if device has NFC chip).
- * - detect whether NFC setting is on or off, and whether it changes from off to on or on to off.
- * - detect incoming data tags or beams.
- *
- * @author Thomas Rorvik Skjolberg
- *
- */
-
-public abstract class NfcDetectorActivity extends Activity {
-
- /**
- * Broadcast Action: The state of the local NFC adapter has been
- * changed.
- * For example, NFC has been turned on or off.
- *
Always contains the extra field {@link #EXTRA_STATE}
- */
-
- public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
-
- /**
- * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
- * intents to request the current power state. Possible values are:
- * {@link #STATE_OFF},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF},
- */
-
- public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
-
- public static final int STATE_OFF = 1;
- public static final int STATE_TURNING_ON = 2;
- public static final int STATE_ON = 3;
- public static final int STATE_TURNING_OFF = 4;
-
- private static final String TAG = NfcDetectorActivity.class.getName();
-
- private static IntentFilter nfcStateChangeIntentFilter = new IntentFilter(ACTION_ADAPTER_STATE_CHANGED);
-
- protected NfcAdapter nfcAdapter;
- protected IntentFilter[] writeTagFilters;
- protected PendingIntent nfcPendingIntent;
-
- protected boolean foreground = false;
- protected boolean intentProcessed = false;
- protected boolean nfcEnabled = false;
-
- protected BroadcastReceiver nfcStateChangeBroadcastReceiver;
-
- protected boolean detecting = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.d(TAG, "onCreate");
-
- // Check for available NFC Adapter
- PackageManager pm = getPackageManager();
- if(!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
- Log.d(TAG, "NFC feature not found");
-
- onNfcFeatureNotFound();
- } else {
- Log.d(TAG, "NFC feature found");
-
- onNfcFeatureFound();
- }
- }
-
- /**
- * Notify that NFC is available
- */
-
- protected void onNfcFeatureFound() {
- initializeNfc();
- detectInitialNfcState();
- }
-
- /**
- *
- * Initialize Nfc fields
- *
- */
-
- protected void initializeNfc() {
- nfcAdapter = NfcAdapter.getDefaultAdapter(this);
- nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
-
- IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
- IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
- IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
- writeTagFilters = new IntentFilter[] {ndefDetected, tagDetected, techDetected};
-
- nfcStateChangeBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final int state = intent.getIntExtra(EXTRA_ADAPTER_STATE, -1);
- if(state == STATE_OFF || state == STATE_ON) {
-
- runOnUiThread(new Runnable() {
- public void run() {
- if(state == STATE_ON) {
- if(detecting) {
- enableForeground();
- }
- }
-
- detectNfcStateChanges();
- }
- });
- }
- }
- };
- }
-
- /**
- *
- * Detect initial NFC state.
- *
- */
-
- protected void detectInitialNfcState() {
- nfcEnabled = nfcAdapter.isEnabled();
- if(nfcEnabled) {
- Log.d(TAG, "NFC is enabled");
-
- onNfcStateEnabled();
- } else {
- Log.d(TAG, "NFC is disabled"); // change state in wireless settings
-
- onNfcStateDisabled();
- }
- }
-
- /**
- *
- * NFC feature was found and is currently enabled
- *
- */
-
- protected abstract void onNfcStateEnabled();
-
- /**
- *
- * NFC feature was found but is currently disabled
- *
- */
-
- protected abstract void onNfcStateDisabled();
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if(nfcAdapter != null) {
- // enable foreground mode if nfc is on and we have started detecting
- boolean enabled = nfcAdapter.isEnabled();
- if(enabled && detecting) {
- enableForeground();
- }
-
- detectNfcStateChanges();
-
- // for quicksettings
- startDetectingNfcStateChanges();
- }
-
- if(!intentProcessed) {
- intentProcessed = true;
-
- processIntent();
- }
-
- }
-
- /**
- *
- * NFC setting changed since last check. For example, the user enabled NFC in the wireless settings.
- *
- */
-
- protected abstract void onNfcStateChange(boolean enabled);
-
- /**
- *
- * Detect changes in NFC settings - enabled/disabled
- *
- */
-
- protected void detectNfcStateChanges() {
- Log.d(TAG, "Detect NFC state changes while previously " + (nfcEnabled ? "enabled" : "disabled"));
-
- boolean enabled = nfcAdapter.isEnabled();
- if(nfcEnabled != enabled) {
- Log.d(TAG, "NFC state change detected; NFC is now " + (enabled ? "enabled" : "disabled"));
- onNfcStateChange(enabled);
-
- nfcEnabled = enabled;
- } else {
- Log.d(TAG, "NFC state remains " + (enabled ? "enabled" : "disabled"));
- }
- }
-
- public void startDetectingNfcStateChanges() {
- registerReceiver(nfcStateChangeBroadcastReceiver, nfcStateChangeIntentFilter);
- }
-
- public void stopDetectingNfcStateChanges() {
- unregisterReceiver(nfcStateChangeBroadcastReceiver);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if(nfcAdapter != null) {
- disableForeground();
-
- // for quicksettings
- stopDetectingNfcStateChanges();
- }
- }
-
- @Override
- public void onNewIntent(Intent intent) {
-
- Log.d(TAG, "onNewIntent");
-
- // onResume gets called after this to handle the intent
- intentProcessed = false;
-
- setIntent(intent);
- }
-
- protected void enableForeground() {
- if(!foreground) {
- Log.d(TAG, "Enable nfc forground mode");
-
- nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
-
- foreground = true;
- }
- }
-
- /**
- *
- * Start detecting NDEF messages
- *
- */
-
- protected void startDetecting() {
- if(!detecting) {
- enableForeground();
-
- detecting = true;
- }
- }
-
- /**
- *
- * Stop detecting NDEF messages
- *
- */
-
- protected void stopDetecting() {
- if(detecting) {
- disableForeground();
-
- detecting = false;
- }
- }
-
- protected void disableForeground() {
- if(foreground) {
- Log.d(TAG, "Disable nfc forground mode");
-
- nfcAdapter.disableForegroundDispatch(this);
-
- foreground = false;
- }
- }
-
- /**
- *
- * Process the current intent, looking for NFC-related actions
- *
- */
-
- public void processIntent() {
- Intent intent = getIntent();
- // Check to see that the Activity started due to an Android Beam
- if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
- Log.d(TAG, "Process NDEF discovered action");
-
- nfcIntentDetected(intent, NfcAdapter.ACTION_NDEF_DISCOVERED);
- } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
- Log.d(TAG, "Process TAG discovered action");
-
- nfcIntentDetected(intent, NfcAdapter.ACTION_TAG_DISCOVERED);
- } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
- Log.d(TAG, "Process TECH discovered action");
-
- nfcIntentDetected(intent, NfcAdapter.ACTION_TECH_DISCOVERED);
- } else {
- Log.d(TAG, "Ignore action " + intent.getAction());
- }
- }
-
- /**
- *
- * Launch an activity for nfc (or wireless) settings, so that the user might enable or disable nfc
- *
- */
-
-
- protected void startNfcSettingsActivity() {
- if (android.os.Build.VERSION.SDK_INT >= 16) {
- startActivity(new Intent(android.provider.Settings.ACTION_NFC_SETTINGS));
- } else {
- startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
- }
- }
-
- /**
- *
- * Incoming NFC communication (in form of tag or beam) detected
- *
- */
-
-
- protected abstract void nfcIntentDetected(Intent intent, String action);
-
- /**
- *
- * This device does not have NFC hardware
- *
- */
-
- protected abstract void onNfcFeatureNotFound();
-
- public boolean isDetecting() {
- return detecting;
- }
-
- public void setDetecting(boolean detecting) {
- this.detecting = detecting;
- }
-
-
-}
diff --git a/Android/Near Field Communications/README.md b/Android/Near Field Communications/README.md
index 6579c21..3762d24 100644
--- a/Android/Near Field Communications/README.md
+++ b/Android/Near Field Communications/README.md
@@ -2,10 +2,10 @@ Near Field Communications overview
==================================
* Close-range radio communication - 4 cm effective range
* Effective for small bursts of data
-* Comes in 'active' and 'passive' forms, typically as in an active mobile device and a passive (sticker) tag
-* Expected smart-phone penetration of 50% by 2013
+* Comes in _active_ and _passive_ forms, typically as in an active mobile device and a passive (sticker) tag
+* Expected smart-phone penetration of 50% by end of 2013 (?).
-Workshop targets
+Workshop / tutorial targets
=========================
* Learn some NDEF format basics
* Compose NDEF messages
@@ -13,11 +13,10 @@ Workshop targets
* Programmatically read NDEF messages into an Android device with NFC support
* Programmatically compose and write NDEF messages
* Send NDEF messages directly between two devices
-* Read application directory of Mifare Desfire EV1 cards
Prerequsistis
=========================
-You must know Android development. If you require help with the basics, we will not have the time to help you.
+You must know Android development. If you require help with the basics, please try other introductory tutorials first.
Requirements - bring this
=========================
@@ -27,14 +26,16 @@ Requirements - bring this
* An USB cable to connect computer and device
* Eclipe with Android SDK installed
* Install [NFC plugin](http://nfc-eclipse-plugin.googlecode.com) from update site http://nfc-eclipse-plugin.googlecode.com/git/nfc-eclipse-plugin-feature/update-site/
-* Check out this (https://github.com/skjolber/Fagmote.git) Git repository. Alternatively, [download zip](https://github.com/skjolber/Fagmote/downloads). Add the projects to your workspace.
+* Check out this (https://github.com/skjolber/Fagmote.git) Git repository. Alternatively, [download zip](https://github.com/skjolber/Fagmote/archive/master.zip).
+* Add all the projects to your workspace __AND MAKE SURE THEY BUILD SUCCESSFULLY__.
+Use the same Android SDK as your phone - update each project correspondingly by right-clicking the project -> Properties -> Android -> Project Build Target and selecting the correct Android SDK version.
-Note that Eclipse is merely required for the NDEF editor, so you can still use your favorite editor for the rest of the tasks. Just make sure the base project imports successfully.
+Note that Eclipse is merely required for the NDEF editor, so you can still use your favorite editor for the rest of the tasks.
Task 1 - Create new NDEF message and write to tag using tool
=========================
### a. Open base project
-Open imported project 'HelloWorldNFC Base'.
+Open imported project __HelloWorldNFC Base__.
### b. Create new NDEF file
Create a new file in the root of the project using New -> Other -> Near Field Communications -> NDEF File.
@@ -42,11 +43,11 @@ Create a new file in the root of the project using New -> Other -> Near Field Co
Hint: NDEF is a data format used in tags.
### c. Add an Android Application Record
1. Read online documentation about [Android Application Records](http://developer.android.com/guide/topics/nfc/nfc.html#aar).
-2. Create an Android Application Record with package name 'no.java.schedule' using the NDEF editor.
+2. Create an Android Application Record with package name __no.java.schedule__ using the NDEF editor.
Hint: Open NDEF file and right-click on the table.
### d. Write the NDEF message to a tag.
-You now have an NDEF message consisting of a single record. Start the 'NFC Developer' application:
+You now have an NDEF message consisting of a single record. Start the __NFC Developer__ Android app, then
1. Scan the custom QR code generated by the NDEF editor.
2. Write by holding a tag to the back of the device.
@@ -54,26 +55,26 @@ You now have an NDEF message consisting of a single record. Start the 'NFC Devel
Hint: If nothing happens, make sure you are holding the tag in the center of the backside of the phone (NFC range is only 4 cm ;-))
Hint: If get tag write IOException, try scanning again a bit slower.
### e. Try out the newly created tag
-Close 'NFC Developer' application and navigate to the home screen. Make sure your Android device is online. What happens when you scan the tag?
+Close the NFC Developer app and navigate to the home screen. Make sure your Android device is online. What happens when you scan the tag?
-Hint: If you do not already have an application with identifier '[no.java.schedule](https://play.google.com/store/search?q=no.java.schedule&c=apps)' installed, Android will search for it at [Google Play](https://play.google.com/store).
+Hint: If you do not already have an application with identifier __[no.java.schedule](https://play.google.com/store/search?q=no.java.schedule&c=apps)__ installed, Android will search for it at [Google Play](https://play.google.com/store).
Task 2 - Discover tag - Hello NFC tag
===========================
### a. Launch Hello World application via NFC
-Launch (run) the empty 'HelloWorldNFC Base' project, so that it gets installed on your device. Then edit the tag from the previuos task so that the Android Application package is __'com.helloworld.nfc'__.
+Launch (run) the empty __HelloWorldNFC Base__ project, so that it gets installed on your device. Update the NDEF message from the previuos task so that the Android Application package is __com.helloworld.nfc__, and write it to the tag.
### b. Change Hello World text by scanning a tag
We want to receieve NFC messages when our application is showing on the screen.
-1. Add NFC [permissions](http://developer.android.com/guide/topics/nfc/nfc.html#manifest) in AndroidMainfest.xml:
+1. Add NFC [permissions](http://developer.android.com/guide/topics/nfc/nfc.html#manifest) in __AndroidMainfest.xml__:
-2. Initialize NFC [foreground mode](http://developer.android.com/guide/topics/nfc/advanced-nfc.html#foreground-dispatch) in the Hello World activity:
+2. Initialize NFC [foreground mode](http://developer.android.com/guide/topics/nfc/advanced-nfc.html#foreground-dispatch) in the __Hello World__ activity:
- @Override
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
@@ -83,7 +84,7 @@ We want to receieve NFC messages when our application is showing on the screen.
}
-3. Call enable/disable foreground mode from onResume() and onPause() in the Hello World activity:
+3. Call enable/disable foreground mode from `onResume(..)` and `onPause(..)` in the __Hello World__ activity:
public void enableForegroundMode() {
Log.d(TAG, "enableForegroundMode");
@@ -97,7 +98,7 @@ We want to receieve NFC messages when our application is showing on the screen.
nfcAdapter.disableForegroundDispatch(this);
}
-4. Change title to 'Hello NFC!' when a tag is scanned:
+4. Change title to __Hello NFC!__ when a tag is scanned:
Add
@Override
@@ -120,7 +121,7 @@ So far we have only detected the tag after the app was started. To detect whenev
-and append the onCreate(..) method with
+and append the `onCreate(..)` method with
if(getIntent().hasExtra(NfcAdapter.EXTRA_TAG)) {
TextView textView = (TextView) findViewById(R.id.title);
@@ -135,7 +136,7 @@ Hint: Relaunch the app and close it. Then scan the tag from the home screen.
Task 3 - Read and analyze tag payload
=============================
### a. Obtain tag NDEF payload
-Check for [NDEF](http://developer.android.com/guide/topics/nfc/nfc.html) messages in method onNewIntent(..) using
+Check for [NDEF](http://developer.android.com/guide/topics/nfc/nfc.html) messages in method `onNewIntent(..)` using
Parcelable[] messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (messages != null) {
@@ -143,16 +144,18 @@ Check for [NDEF](http://developer.android.com/guide/topics/nfc/nfc.html) message
}
Verify that messages appear in the log.
-### b. Get the NdefMessage.
-Cast the first messages element into the Android class NdefMessage:
+### b. Get the NDEF Message.
+Cast the first messages element into the Android class `NdefMessage`:
NdefMessage ndefMessage = (NdefMessage)messages[0];
-and log the number of NdefRecords within the ndefMessage. How does the NdefRecord class compare to the NDEF records we saw in the NDEF editor in task 1?
+and log the number of `NdefRecords` within the `ndefMessage` variable. How does the `NdefRecord` class compare to the NDEF records we saw in the NDEF editor in task 1?
+
+Hint: In the present form, the NDEF Record is not very friendly.
-### c. Parse NdefMessage using [NDEF Tools for Android](http://code.google.com/p/ndef-tools-for-android/)
+### c. Parse NDEF Message using the [NDEF Tools for Android](http://code.google.com/p/ndef-tools-for-android/) library
-Parse ndefMessage from previous task into Records using
+Parse `ndefMessage` from previous task into a list of `Record` using
// parse to high-level records
try {
@@ -187,11 +190,10 @@ The tag id can be a useful attribute. Log the tag id by adding a call to
Log.d(TAG, "Tag id is " + toHexString(byteArrayExtra));
}
}
-
+and verify that it is working. How many bytes is the tag id?
Task 4 - Compose and write tag payload
=======================================
-Open imported project 'HelloWorldNFC Base'.
-### a. Compose an NDEF message using [NDEF Tools for Android](http://code.google.com/p/ndef-tools-for-android/)
+### a. Compose an NDEF message using the [NDEF Tools for Android](http://code.google.com/p/ndef-tools-for-android/) library
public Message composeMessage(String text) {
Log.d(TAG, "createMessage");
@@ -209,14 +211,14 @@ Open imported project 'HelloWorldNFC Base'.
}
### b. Write the message when tag is scanned
-1. Convert Message to ndefMessage
-We need to convert our high-level objects to the Android native low-level equivalent.
+1. Convert `Message` to `ndefMessage`.
+We need to convert our high-level objects to the Android native low-level equivalent. Add in method `onNewIntent()`:
- Message composedMessage = composeMessage("1);
+ Message composedMessage = composeMessage("1");
NdefMessage composedMessageNdefMessage = composedMessage.getNdefMessage();
2. Write to tag
-Add the following code. Call the method from onNewIntent() if a tag is detected.
+Add the following code. Call the method from `onNewIntent()` if a tag is detected, after the above lines.
public boolean write(NdefMessage rawMessage, Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
@@ -250,7 +252,7 @@ Add the following code. Call the method from onNewIntent() if a tag is detected.
return false;
}
-3. Update gui text on write success or failure.
+3. Update GUI text on write success or failure.
if(write(composedMessageNdefMessage, intent)) {
Log.d(TAG, "Write success!");
@@ -265,25 +267,27 @@ Add the following code. Call the method from onNewIntent() if a tag is detected.
then verify that the code is working. Do you see the new Text Record in the log the second time you scan the tag?
### c. Increment the integer stored in the Text Record on tag scan
-In the onNewIntent() method
+In the `onNewIntent()` method
1. Detect og read the NDEF message and filter out the Text Record.
2. Get the Text Record text, parse and increment the number
3. Compose a new NDEF message and write it to the tag
4. Update the GUI with the resulting number
+Hint: Use the `instanceof` operator to check the record type.
+
Task 5 - device to device communication: Android Beam
=====================================================
Use [Android Beam](http://developer.android.com/guide/topics/nfc/nfc.html#p2p) to exchange information between two devices.
### a. Register push message callback interface
-Read about the [NfcAdapter.CreateNdefMessageCallback](http://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback.html) interface and register callback in the activity 'onCreate()' method using
+Read about the [NfcAdapter.CreateNdefMessageCallback](http://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback.html) interface and register callback in the activity `onCreate()` method using
// Register Android Beam callback
nfcAdapter.setNdefPushMessageCallback(this, this);
### b. Compose push message
-Implement method 'createNdefMessage(..) - compose the NdefMessage to be pushed:
+Implement method `createNdefMessage(..)` - for composing the `NdefMessage` to be pushed:
Log.d(TAG, "createNdefMessage");
@@ -301,21 +305,26 @@ Implement method 'createNdefMessage(..) - compose the NdefMessage to be pushed:
return message.getNdefMessage();
### c. Push message between two devices
+__Make sure to first disable the tag write functionality.__
+
Hold two devices together and see what happens. When a is message pushed from one NFC device to another?
-### d. Read pushed message (on the receiver side)
-Are you able to filter out the right external type record on the reciever side?
+### d. Read pushed message (on the receiver side).
+
+Are you able to filter out the right External Type record on the reciever side?
+
Hint 1: A pushed NDEF message can be read the same was as a tag
-Hint 2: The Android Application Record is also an External Type record.
+
+Hint 2: The Android Application Record is also an [External Type](http://developer.android.com/reference/android/nfc/NdefRecord.html#createExternal(java.lang.String, java.lang.String, byte[]) record.
### e. Post push message notification
Use the [NfcAdapter.OnNdefPushCompleteCallback](http://developer.android.com/reference/android/nfc/NfcAdapter.OnNdefPushCompleteCallback.html) interface to show a notification when a message is pushed using Android Beam.
-First register callback in 'onCreate(..)'
+First register callback in `onCreate(..)`
// Register callback to listen for message-sent success
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
-Then implement the 'onNdefPushComplete(..)' method:
+Then implement the `onNdefPushComplete(..)` method:
// Handle push success
@Override
@@ -334,113 +343,6 @@ Then implement the 'onNdefPushComplete(..)' method:
Verify that everything is working by holding two phones together. Reflect over the user-friendliness of transferring a lot of data holding two devices together in this way - what would be a more practical approach in such a scenario?
-Task 6 - Mifare Desfire EV1 intro
-==========================
-So far we have relied on the Android NFC subsystem to abstract away the actual NFC tag communication details. Lets look at the [Mifare Desfire EV1 card](http://www.nxp.com/products/identification_and_security/smart_card_ics/mifare_smart_card_ics/mifare_desfire/).
-
-### a. Open base project
-Open imported project 'HelloWorldNFC Desfire Base'. Open the MainActivity class.
-
-### b. Identify Desfire EV1 tag type.
-Android supplies multiple technology-specific classes for low-level access, depending on the tag type and its contents. The [IsoDep](http://developer.android.com/reference/android/nfc/tech/IsoDep.html) class is responsible for interacting with Desfire EV1 cards.
-
-Add the following code to the nfcIntentDetected(..) method:
-
- Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- if(tag != null) {
- IsoDep isoDep = null;
- String[] techList = tag.getTechList();
- for (String tech : techList) {
- Log.d(TAG, "Tech " + tech);
-
- if (tech.equals(android.nfc.tech.IsoDep.class.getName())) {
- isoDep = android.nfc.tech.IsoDep.get(tag);
- }
- }
- if(isoDep != null) {
- Log.d(TAG, "Detected Desfire tag");
- TextView textView = (TextView) findViewById(R.id.title);
- textView.setText("Desfire tag!");
- } else {
- Log.d(TAG, "Did not detect a Desfire tag");
-
- TextView textView = (TextView) findViewById(R.id.title);
- textView.setText("Unknown tag!");
- }
- }
-
-### c. Read tag metadata
-Use the __DesfireReader__ class to read some basic tag metadata:
-
- try {
- isoDep.connect();
-
- DesfireReader reader = new DesfireReader(isoDep);
-
- VersionInfo versionInfo = reader.getVersionInfo();
- Log.d(TAG, "Tag ID " + toHexString(versionInfo.getUid()));
- Log.d(TAG, "Hardware version " + versionInfo.getHardwareVersion() + ", software version " + versionInfo.getSoftwareVersion());
- Log.d(TAG, "Hardware capacity " + versionInfo.getHardwareStorageSize() + ", software capacity " + versionInfo.getSoftwareStorageSize());
- } catch (Exception e) {
- Log.d(TAG, "Problem accessing Desfire tag", e);
- } finally {
- try {
- isoDep.close();
- } catch (IOException e) {
- // ignore
- }
- }
-
-What is the tag storage capacity for this tag?
-
-### d. Read tag application directory
-Desfire EV1 files have a more structured nature that most tags. The tag storage area consists of a directory of Applications and then Files within each Application. The Add
-
- int[] applicationDirectory = reader.getApplicationDirectory();
- Log.d(TAG, "Read " + applicationDirectory.length + " apps");
-
- for (int i = 0; i < applicationDirectory.length; i++) {
- reader.selectApplication(applicationDirectory[i]);
- int[] fileList = reader.getFiles();
- Log.d(TAG, "App " + Integer.toHexString(applicationDirectory[i]) + " at index " + i + " has " + fileList.length + " files");
- }
-
-### e. Read the files within each application
-Add
-
- for (int k = 0; k < fileList.length; k++) {
- DesfireFileSettings fileSettings = reader.getFileSettings(fileList[k]);
-
- Log.d(TAG, "Read file " + k + " settings " + fileSettings.getClass().getSimpleName() + " 0x" + Integer.toHexString(fileList[k]) + " " + fileSettings.getFileTypeName());
-
- // print file read and writes access
- if(fileSettings.freeReadAccess()) {
- Log.d(TAG, "File " + k + " is readable");
- }
- if(fileSettings.freeWriteAccess()) {
- Log.d(TAG, "File " + k + " is writable");
- }
-
- byte[] fileContents = reader.readFile(fileList[k]);
-
- Log.d(TAG, "Read " + fileContents.length + " bytes for file " + k);
- }
-
-Does the fileContents byte array contain any familiar data?
-Hint: Create a String from the byte-array.
-
-What other highly desirable functions than multi-Application support does the Desfire EV1 cards have?
-
-Bonus task - more NDEF record types
-===================================
-### a. How would you make NFC support optional?
-Not all devices have NFC chips (yet)
-### b. What are the tag classes and their storage capactiy?
-What are the disadvantage of larger storage capacities?
-### c. Create more record types
-1. Create well-known URI record.
-2. Create Mime Record.
-3. Create your own External type Record.
-
-
-
+You are done!
+========================
+That concludes this workshop / tutorial. The original version of this material can be found at the [greenbird Git repo](https://github.com/greenbird/workshops).