Monday, January 28, 2013

NFC Android Tutorial

Overview

NFC (Near Field Communication) is set of standards that enable smartphones and similar devices to establish a radio communication*( requires a distance of 4cm or less to initiate a connection) and allows to transfer data such as text or numbers between two NFC enabled devices.
In practice, NFC enables simple and safe two- way interactions among electronic devices within a close proximity
NFC standards are  based on RFID (radio frequency identification) standards.

NFC

Device should be NFC enabled to use this technology


Nfc Features
•  Short range technology
                  –  Connection established when devices or tag close enough (5-10 cm)
                  –  Simple setup (instant configuration)
•  2-way communication
                  –  Not only reading like in contactless smart cards, but data exchange
•  Passive tags
                  –  No need for external power
                  –  Low-price
•  Security
                  –  Support secure element
                  –  Close proximity use brings some basic security
What  can we store in NFC tags?

We can store variety of data on NFC TAG. The actual amount of data varies depending on the type of NFC tag used - different tags have different memory capacities.  A standard Ultralight nfc tag can  store a URL of around 41 characters, while NTAG203   can store data around 132 characters.
Usually, this information is stored in a specific data format (NDEF - NFC data exchange format) so that it can be reliably read by most devices and mobile phones.

Nfc Modes

•  Read and write tags
•  Peer-to-peer
•  Card emulation

Android Support
          –  Read and write (excellent support)
P2P (limited)

Requirements for using NFC enabled application

Most Important requirement for a device is that it should have required hardware to support NFC feature
here is the list of NFC enabled mobile devices

Minimum API required

API level 9 only supports limited tag dispatch via Action_Tag_Discovered and only gives access to NDEF messages via the EXTRA_NDEF_MESSAGE extra. No other tag properties or I/O operations are accessible. API level 10 includes comprehensive reader/writer support as well as foreground NDEF pushing, and API level 14 provides an easier way to push NDEF messages to other devices with Android Beam and extra convenience methods to create NDEF records.

Permissions required for Android application to use NFC

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

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

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

Key Players

NfcManager  is the high level manager, used to obtain this device's NfcAdapter.
NfcAdapter  represents the device's NFC adapter, which is your entry-point to performing NFC operations
NdefMessage Represents NDEF data message, which is the standard format in which "records" carrying data are transmitted between devices and tags. Your application can receive these messages from ACTION_TAG_DISCOVERED ntent.
NdefRecord Represents a record, which is delivered in a NdefMessage and describes the type of data being shared and carries the data itself.
How NFC tags are read
Reading NDEF data from an NFC tag is handled with the tag dispatch system , which analyzes discovered NFC tags, appropriately categorizes the data, and starts an application that is interested in the categorized data. An application that wants to handle the scanned NFC tag can declare an intent filter and request to handle the data.

Enabling foreground
/**
* Enables foreground intent detection
*/
    public void enableForeground() {

        if(!foreground) {

            IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            writeTagFilters = new IntentFilter[] {tagDetected, ndefDetected};
            nfcAdapter.enableForegroundDispatch(context, nfcPendingIntent, writeTagFilters, null);

            foreground = true;
        }
    }



Now we create a IntentFilter, to tell Android that our application is enabled to work on nfc tag (NfcAdapter.ACTION_TAG_DISCOVERED). We register our app with an intentFilter in the Manifest.

<activity android:name="com.example.activity.NfcReaderActivity" >
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
method to read nfc tag

/**
     * Reads the ndef messages from the given intent
     *
     * @param intent
     * @return true if messages were extracted
     */
    public boolean read(Intent intent) {
        Log.d(TAG, "Read intent");

        Parcelable[] messages = intent
                .getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (messages != null) {
            NdefMessage[] ndefMessages = new NdefMessage[messages.length];
            for (int i = 0; i < messages.length; i++) {
                ndefMessages[i] = (NdefMessage) messages[i];
            }

            if (ndefMessages.length > 0) {
                listener.readNdefMessages(ndefMessages);

                return true;
            } else {
                listener.readNdefEmptyMessage();
            }
        } else {
            listener.readNonNdefMessage();
        }

        return false;
    }
­
Writing NFC tags
­
    public boolean write(final NdefMessage message, Intent intent) {
        final Tag extra = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        Thread t = new Thread(new Runnable() {
            Tag tag = extra;

            @Override
            public void run() {
        NdefFormatable format = NdefFormatable.get(tag);
        if (format != null) {
            Log.d(TAG, "Write unformatted tag");
            try {
                format.connect();
                format.format(message);

                listener.wroteNdefUnformatted();

                        return;
            } catch (Exception e) {
                listener.writeNdefUnformattedFailed(e);
            }
                    finally{
                        try {
                            format.close();
                        } catch (IOException e) {
                            Log.d(TAG, "Cannot close connection to the tag.");
                        }
                    }
            Log.d(TAG, "Cannot write unformatted tag");
        } else {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                try {
                    Log.d(TAG, "Write formatted tag");

                    ndef.connect();
                    if (!ndef.isWritable()) {
                        Log.d(TAG, "Tag is not writeable");

                        listener.writeNdefNotWritable();

                                return;
                    }
                    if (ndef.getMaxSize() < message.toByteArray().length) {
                        Log.d(TAG,
                                "Tag size is too small, have "
                                        + ndef.getMaxSize() + ", need "
                                        + message.toByteArray().length);

                        listener.writeNdefTooSmall(
                                message.toByteArray().length, ndef.getMaxSize());

                                return;
                    }
                    ndef.writeNdefMessage(message);

                    listener.wroteNdefFormatted();

                            return;
                } catch (Exception e) {
                    listener.writeNdefFormattedFailed(e);
                }
            } else {
                listener.writeNdefCannotWriteTech();
            }
            Log.d(TAG, "Cannot write formatted tag");
        }

            }
        });

        t.run();
        return success;
    }

Sources:
 download the nfctools.jar file from here

No comments:

Post a Comment