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>