Home | History | Annotate | Download | only in nfc
      1 page.title=Advanced NFC
      2 @jd:body
      3 
      4 <div id="qv-wrapper">
      5 <div id="qv">
      6   <h2>In this document</h2>
      7   <ol>
      8     <li><a href="#tag-tech">Working with Supported Tag Technologies</a>
      9       <ol>
     10         <li><a href="#tech-intent">Working with tag technologies and the ACTION_TECH_DISCOVERED
     11         intent</a></li>
     12         <li><a href="#read-write">Reading and writing to tags</a></li>
     13       </ol></li>
     14     <li><a href="#foreground-dispatch">Using the Foreground Dispatch System</a></li>
     15   </ol>
     16 </div>
     17 </div>
     18 
     19 <p>This document describes advanced NFC topics, such as working with various tag technologies,
     20 writing to NFC tags, and foreground dispatching, which allows an application in the foreground to
     21 handle intents even when other applications filter for the same ones.</p>
     22 
     23 <h2 id="tag-tech">Working with Supported Tag Technologies</h2>
     24 <p>When working with NFC tags and Android-powered devices, the main format you use to read
     25 and write data on tags is NDEF. When a device scans a tag with NDEF data, Android provides support
     26 in parsing the message and delivering it in an {@link android.nfc.NdefMessage} when
     27 possible. There are cases, however, when you scan a tag that does not contain
     28 NDEF data or when the NDEF data could not be mapped to a MIME type or URI.
     29 In these cases, you need to open communication directly with the tag and read and write to it with
     30 your own protocol (in raw bytes). Android provides generic support for these use cases with the
     31 {@link android.nfc.tech} package, which is described in <a href="#tech-table">Table 1</a>. You can
     32 use the {@link android.nfc.Tag#getTechList getTechList()} method to determine the technologies
     33 supported by the tag and create the corresponding {@link android.nfc.tech.TagTechnology}
     34 object with one of classes provided by {@link android.nfc.tech} </p>
     35 
     36 <p class="table-caption" id="table1">
     37 <strong>Table 1.</strong> Supported tag technologies</p>
     38 <table id="tech-table">
     39 
     40     <tr>
     41       <th>Class</th>
     42 
     43       <th>Description</th>
     44     </tr>
     45 
     46     <tr>
     47       <td>{@link android.nfc.tech.TagTechnology}</td>
     48 
     49       <td>The interface that all tag technology classes must implement.</td>
     50     </tr>
     51 
     52     <tr>
     53       <td>{@link android.nfc.tech.NfcA}</td>
     54 
     55       <td>Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.</td>
     56     </tr>
     57 
     58     <tr>
     59       <td>{@link android.nfc.tech.NfcB}</td>
     60 
     61       <td>Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.</td>
     62     </tr>
     63 
     64     <tr>
     65       <td>{@link android.nfc.tech.NfcF}</td>
     66 
     67       <td>Provides access to NFC-F (JIS 6319-4) properties and I/O operations.</td>
     68     </tr>
     69 
     70     <tr>
     71       <td>{@link android.nfc.tech.NfcV}</td>
     72 
     73       <td>Provides access to NFC-V (ISO 15693) properties and I/O operations.</td>
     74     </tr>
     75 
     76     <tr>
     77       <td>{@link android.nfc.tech.IsoDep}</td>
     78 
     79       <td>Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.</td>
     80     </tr>
     81 
     82     <tr>
     83       <td>{@link android.nfc.tech.Ndef}</td>
     84 
     85       <td>Provides access to NDEF data and operations on NFC tags that have been formatted as
     86       NDEF.</td>
     87     </tr>
     88 
     89     <tr>
     90       <td>{@link android.nfc.tech.NdefFormatable}</td>
     91 
     92       <td>Provides a format operations for tags that may be NDEF formattable.</td>
     93     </tr>
     94   </table>
     95 <p>The following tag technlogies are not required to be supported by Android-powered devices.</p>
     96   <p class="table-caption" id="table2">
     97 <strong>Table 2.</strong> Optional supported tag technologies</p>
     98   <table>
     99     <tr>
    100       <th>Class</th>
    101 
    102       <th>Description</th>
    103     </tr>
    104     <tr>
    105       <td>{@link android.nfc.tech.MifareClassic}</td>
    106 
    107       <td>Provides access to MIFARE Classic properties and I/O operations, if this Android device
    108       supports MIFARE.</td>
    109     </tr>
    110 
    111     <tr>
    112       <td>{@link android.nfc.tech.MifareUltralight}</td>
    113 
    114       <td>Provides access to MIFARE Ultralight properties and I/O operations, if this Android
    115       device supports MIFARE.</td>
    116     </tr>
    117   </table>
    118 
    119 <h3 id="tech-intent">Working with tag technologies and the ACTION_TECH_DISCOVERED intent</h3>
    120 <p>When a device scans a tag that has NDEF data on it, but could not be mapped to a MIME or URI,
    121 the tag dispatch system tries to start an activity with the {@link
    122 android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}
    123 intent. The {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} is also used when a tag
    124 with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag
    125 directly if the tag dispatch system could not parse it for you. The basic steps when working with
    126 tag technologies are as follows:</p>
    127 
    128 <ol>
    129   <li>Filter for an {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent specifying the
    130 tag technologies that you want to handle. See <a
    131 href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#tech-disc">Filtering for NFC
    132 intents</a> for more information. In general, the tag dispatch system tries to start a {@link
    133 android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent when an NDEF message
    134 cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For
    135 more information on how this is determined, see <a
    136 href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#tag-dispatch">The Tag Dispatch System</a>.</li>
    137   <li>When your application receives the intent, obtain the {@link android.nfc.Tag} object from
    138 the intent:
    139 <pre>Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);</pre></li>
    140 <li>Obtain an instance of a {@link android.nfc.tech.TagTechnology}, by calling one of the
    141 <code>get</code> factory methods of the classes in the {@link android.nfc.tech} package. You can
    142 enumerate the supported technologies of the tag by calling {@link android.nfc.Tag#getTechList
    143 getTechList()} before calling a <code>get</code> factory method. For example, to obtain an instance
    144 of {@link android.nfc.tech.MifareUltralight} from a {@link android.nfc.Tag}, do the following:
    145 
    146 <pre>
    147 MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
    148 </pre>
    149 </li>
    150 </ol>
    151 
    152 
    153 
    154 <h3 id="read-write">Reading and writing to tags</h3>
    155 
    156 <p>Reading and writing to an NFC tag involves obtaining the tag from the intent and
    157 opening communication with the tag. You must define your own protocol stack to read and write data
    158 to the tag. Keep in mind, however, that you can still read and write NDEF data when working
    159 directly with a tag. It is up to you how you want to structure things. The
    160 following example shows how to work with a MIFARE Ultralight tag.</p>
    161 
    162 <pre>
    163 package com.example.android.nfc;
    164 
    165 import android.nfc.Tag;
    166 import android.nfc.tech.MifareUltralight;
    167 import android.util.Log;
    168 import java.io.IOException;
    169 import java.nio.charset.Charset;
    170 
    171 public class MifareUltralightTagTester {
    172 
    173     private static final String TAG = MifareUltralightTagTester.class.getSimpleName();
    174 
    175     public void writeTag(Tag tag, String tagText) {
    176         MifareUltralight ultralight = MifareUltralight.get(tag);
    177         try {
    178             ultralight.connect();
    179             ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII")));
    180             ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII")));
    181             ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII")));
    182             ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII")));
    183         } catch (IOException e) {
    184             Log.e(TAG, "IOException while closing MifareUltralight...", e);
    185         } finally {
    186             try {
    187                 ultralight.close();
    188             } catch (IOException e) {
    189                 Log.e(TAG, "IOException while closing MifareUltralight...", e);
    190             }
    191         }
    192     }
    193 
    194     public String readTag(Tag tag) {
    195         MifareUltralight mifare = MifareUltralight.get(tag);
    196         try {
    197             mifare.connect();
    198             byte[] payload = mifare.readPages(4);
    199             return new String(payload, Charset.forName("US-ASCII"));
    200         } catch (IOException e) {
    201             Log.e(TAG, "IOException while writing MifareUltralight
    202             message...", e);
    203         } finally {
    204             if (mifare != null) {
    205                try {
    206                    mifare.close();
    207                }
    208                catch (IOException e) {
    209                    Log.e(TAG, "Error closing tag...", e);
    210                }
    211             }
    212         }
    213         return null;
    214     }
    215 }
    216 </pre>
    217 
    218 </pre>
    219 
    220   <h2 id="foreground-dispatch">Using the Foreground Dispatch System</h2>
    221 
    222   <p>The foreground dispatch system allows an activity to intercept an intent and claim
    223 priority over other activities that handle the same intent. Using this system involves
    224   constructing a few data structures for the Android system to be able to send the appropriate
    225   intents to your application. To enable the foreground dispatch system:</p>
    226 
    227   <ol>
    228     <li>Add the following code in the <code>onCreate()</code> method of your activity:
    229 
    230       <ol>
    231         <li>Create a {@link android.app.PendingIntent} object so the Android system can populate it
    232         with the details of the tag when it is scanned.
    233           <pre>
    234 PendingIntent pendingIntent = PendingIntent.getActivity(
    235     this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    236 </pre>
    237         </li>
    238 
    239         <li>Declare intent filters to handle the intents that you want to intercept. The foreground
    240         dispatch system checks the specified intent filters with the intent that is received when
    241         the device scans a tag. If it matches, then your application handles the intent. If it does
    242         not match, the foreground dispatch system falls back to the intent dispatch system.
    243         Specifying a <code>null</code> array of intent filters and technology filters, specifies
    244         that you want to filter for all tags that fallback to the <code>TAG_DISCOVERED</code>
    245         intent. The code snippet below handles all MIME types for <code>NDEF_DISCOVERED</code>. You
    246         should only handle the ones that you need.
    247 <pre>
    248 IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    249     try {
    250         ndef.addDataType("*/*");    /* Handles all MIME based dispatches.
    251                                        You should specify only the ones that you need. */
    252     }
    253     catch (MalformedMimeTypeException e) {
    254         throw new RuntimeException("fail", e);
    255     }
    256    intentFiltersArray = new IntentFilter[] {ndef, };
    257 </pre>
    258         </li>
    259 
    260         <li>Set up an array of tag technologies that your application wants to handle. Call the
    261         <code>Object.class.getName()</code> method to obtain the class of the technology that you
    262         want to support.
    263 <pre>
    264 techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
    265 </pre>
    266         </li>
    267       </ol>
    268     </li>
    269 
    270     <li>Override the following activity lifecycle callbacks and add logic to enable and disable the
    271     foreground dispatch when the activity loses ({@link android.app.Activity#onPause onPause()})
    272     and regains ({@link android.app.Activity#onResume onResume()}) focus. {@link
    273     android.nfc.NfcAdapter#enableForegroundDispatch enableForegroundDispatch()} must be called from
    274 the main thread and only  when the activity is in the foreground (calling in {@link
    275 android.app.Activity#onResume onResume()} guarantees this). You also need to implement the {@link
    276     android.app.Activity#onNewIntent onNewIntent} callback to process the data from the scanned NFC
    277     tag.</li>
    278 
    279 <pre>
    280 public void onPause() {
    281     super.onPause();
    282     mAdapter.disableForegroundDispatch(this);
    283 }
    284 
    285 public void onResume() {
    286     super.onResume();
    287     mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
    288 }
    289 
    290 public void onNewIntent(Intent intent) {
    291     Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    292     //do something with tagFromIntent
    293 }
    294 </pre>
    295     </li>
    296   </ol>
    297 
    298   <p>See the <a href=
    299 "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html">
    300 ForegroundDispatch</a> sample from API Demos for the complete sample.</p>