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