1page.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, 20writing to NFC tags, and foreground dispatching, which allows an application in the foreground to 21handle 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 25and write data on tags is NDEF. When a device scans a tag with NDEF data, Android provides support 26in parsing the message and delivering it in an {@link android.nfc.NdefMessage} when 27possible. There are cases, however, when you scan a tag that does not contain 28NDEF data or when the NDEF data could not be mapped to a MIME type or URI. 29In these cases, you need to open communication directly with the tag and read and write to it with 30your 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 32use the {@link android.nfc.Tag#getTechList getTechList()} method to determine the technologies 33supported by the tag and create the corresponding {@link android.nfc.tech.TagTechnology} 34object 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, 121the tag dispatch system tries to start an activity with the {@link 122android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} 123intent. The {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} is also used when a tag 124with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag 125directly if the tag dispatch system could not parse it for you. The basic steps when working with 126tag technologies are as follows:</p> 127 128<ol> 129 <li>Filter for an {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent specifying the 130tag technologies that you want to handle. See <a 131href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#tech-disc">Filtering for NFC 132intents</a> for more information. In general, the tag dispatch system tries to start a {@link 133android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent when an NDEF message 134cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For 135more information on how this is determined, see <a 136href="{@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 138the 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 142enumerate the supported technologies of the tag by calling {@link android.nfc.Tag#getTechList 143getTechList()} before calling a <code>get</code> factory method. For example, to obtain an instance 144of {@link android.nfc.tech.MifareUltralight} from a {@link android.nfc.Tag}, do the following: 145 146<pre> 147MifareUltralight.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 157opening communication with the tag. You must define your own protocol stack to read and write data 158to the tag. Keep in mind, however, that you can still read and write NDEF data when working 159directly with a tag. It is up to you how you want to structure things. The 160following example shows how to work with a MIFARE Ultralight tag.</p> 161 162<pre> 163package com.example.android.nfc; 164 165import android.nfc.Tag; 166import android.nfc.tech.MifareUltralight; 167import android.util.Log; 168import java.io.IOException; 169import java.nio.charset.Charset; 170 171public 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 223priority 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> 234PendingIntent 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> 248IntentFilter 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> 264techListsArray = 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 274the main thread and only when the activity is in the foreground (calling in {@link 275android.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> 280public void onPause() { 281 super.onPause(); 282 mAdapter.disableForegroundDispatch(this); 283} 284 285public void onResume() { 286 super.onResume(); 287 mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); 288} 289 290public 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"> 300ForegroundDispatch</a> sample from API Demos for the complete sample.</p>