Merge "cherrypick from master - docs: nfc updates Change-Id: Iaa782911f14b11bc896ac9ef06db2c43104d1dac" into ics-mr0

This commit is contained in:
Robert Ly
2011-10-18 11:11:05 -07:00
committed by Android (Google) Code Review
5 changed files with 1275 additions and 612 deletions

View File

@@ -262,20 +262,20 @@
</ul> </ul>
</li> </li>
<li class="toggle-list"> <li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html"> <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
<span class="en">RenderScript</span> <span class="en">RenderScript</span></a>
</a></div> </div>
<ul> <ul>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html"> <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
<span class="en">Graphics</span> <span class="en">Graphics</span>
</a> </a>
</li> </li>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html"> <li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html">
<span class="en">Compute</span> <span class="en">Compute</span>
</a> </a>
</li> </li>
</ul> </ul>
</li> </li>
<li class="toggle-list"> <li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/media/index.html"> <div><a href="<?cs var:toroot ?>guide/topics/media/index.html">
@@ -332,9 +332,15 @@
<li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html"> <li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
<span class="en">Bluetooth</span></a> <span class="en">Bluetooth</span></a>
</li> </li>
<li><a href="<?cs var:toroot?>guide/topics/nfc/index.html"> <li class="toggle-list">
<span class="en">Near Field Communication</span> <div><a href="<?cs var:toroot?>guide/topics/nfc/index.html">
</a></li> <span class="en">Near Field Communication</span></a> <span class="new">updated</span>
</div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/nfc/nfc.html">NFC Basics</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/nfc/advanced-nfc.html">Advanced NFC</a></li>
</ul>
</li>
<li class="toggle-list"> <li class="toggle-list">
<div><a href="<?cs var:toroot?>guide/topics/usb/index.html"> <div><a href="<?cs var:toroot?>guide/topics/usb/index.html">
<span class="en">USB</span></a> <span class="en">USB</span></a>
@@ -715,7 +721,7 @@
<li class="toggle-list"> <li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html"> <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">
<span class="en">UI Guidelines</span> <span class="en">UI Guidelines</span>
</a></div> </a> <span class="new-child">updated</span></div>
<ul> <ul>
<li class="toggle-list"> <li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html"> <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html">

View File

@@ -0,0 +1,303 @@
page.title=Advanced NFC
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#tag-tech">Working with Supported Tag Technologies</a>
<ol>
<li><a href="#tech-intent">Working with tag technologies and the ACTION_TECH_DISCOVERED
intent</a></li>
<li><a href="#read-write">Reading and writing to tags</a></li>
</ol></li>
<li><a href="#foreground-dispatch">Using the Foreground Dispatch System</a></li>
</ol>
</div>
</div>
<p>This document describes advanced NFC topics, such as working with various tag technologies,
writing to NFC tags, and foreground dispatching, which allows an application in the foreground to
handle intents even when other applications filter for the same ones.</p>
<h2 id="tag-tech">Working with Supported Tag Technologies</h2>
<p>When working with NFC tags and Android-powered devices, the main format you use to read
and write data on tags is NDEF. When a device scans a tag with NDEF data, Android provides support
in parsing the message and delivering it in an {@link android.nfc.NdefMessage} when
possible. There are cases, however, when you scan a tag that does not contain
NDEF data or when the NDEF data could not be mapped to a MIME type or URI.
In these cases, you need to open communication directly with the tag and read and write to it with
your own protocol (in raw bytes). Android provides generic support for these use cases with the
{@link android.nfc.tech} package, which is described in <a href="#tech-table">Table 1</a>. You can
use the {@link android.nfc.Tag#getTechList getTechList()} method to determine the technologies
supported by the tag and create the corresponding {@link android.nfc.tech.TagTechnology}
object with one of classes provided by {@link android.nfc.tech} </p>
<table>
<p class="table-caption" id="table1">
<strong>Table 1.</strong> Supported tag technologies</p>
<table id="tech-table">
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td>{@link android.nfc.tech.TagTechnology}</td>
<td>The interface that all tag technology classes must implement.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcA}</td>
<td>Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcB}</td>
<td>Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcF}</td>
<td>Provides access to NFC-F (JIS 6319-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcV}</td>
<td>Provides access to NFC-V (ISO 15693) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.IsoDep}</td>
<td>Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.Ndef}</td>
<td>Provides access to NDEF data and operations on NFC tags that have been formatted as
NDEF.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NdefFormatable}</td>
<td>Provides a format operations for tags that may be NDEF formattable.</td>
</tr>
</table>
<p>The following tag technlogies are not required to be supported by Android-powered devices.</p>
<p class="table-caption" id="table2">
<strong>Table 2.</strong> Optional supported tag technologies</p>
<table>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareClassic}</td>
<td>Provides access to MIFARE Classic properties and I/O operations, if this Android device
supports MIFARE.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareUltralight}</td>
<td>Provides access to MIFARE Ultralight properties and I/O operations, if this Android
device supports MIFARE.</td>
</tr>
</table>
<h3 id="tech-intent">Working with tag technologies and the ACTION_TECH_DISCOVERED intent</h3>
<p>When a device scans a tag that has NDEF data on it, but could not be mapped to a MIME or URI,
the tag dispatch system tries to start an activity with the {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}
intent. The {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} is also used when a tag
with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag
directly if the tag dispatch system could not parse it for you. The basic steps when working with
tag technologies are as follows:</p>
<ol>
<li>Filter for an {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent specifying the
tag technologies that you want to handle. See <a
href="{@docRoot}guide/topics/nfc/nfc.html#tech-disc">Filtering for NFC
intents</a> for more information. In general, the tag dispatch system tries to start a {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent when an NDEF message
cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For
more information on how this is determined, see <a
href="{@docRoot}guide/topics/nfc/nfc.html#tag-dispatch">The Tag Dispatch System</a>.</li>
<li>When your application receives the intent, obtain the {@link android.nfc.Tag} object from
the intent:
<pre>Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);</pre></li>
<li>Obtain an instance of a {@link android.nfc.tech.TagTechnology}, by calling one of the
<code>get</code> factory methods of the classes in the {@link android.nfc.tech} package. You can
enumerate the supported technologies of the tag by calling {@link android.nfc.Tag#getTechList
getTechList()} before calling a <code>get</code> factory method. For example, to obtain an instance
of {@link android.nfc.tech.MifareUltralight} from a {@link android.nfc.Tag}, do the following:
<pre>
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
</pre>
</li>
</ol>
<h3 id="read-write">Reading and writing to tags</h3>
<p>Reading and writing to an NFC tag involves obtaining the tag from the intent and
opening communication with the tag. You must define your own protocol stack to read and write data
to the tag. Keep in mind, however, that you can still read and write NDEF data when working
directly with a tag. It is up to you how you want to structure things. The
following example shows how to work with a MIFARE Ultralight tag.</p>
<pre>
package com.example.android.nfc;
import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;
public class MifareUltralightTagTester {
private static final String TAG = MifareUltralightTagTester.class.getSimpleName();
public void writeTag(Tag tag, String tagText) {
MifareUltralight ultralight = MifareUltralight.get(tag);
try {
ultralight.connect();
ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII")));
} catch (IOException e) {
Log.e(TAG, "IOException while closing MifareUltralight...", e);
} finally {
try {
ultralight.close();
} catch (IOException e) {
Log.e(TAG, "IOException while closing MifareUltralight...", e);
}
}
}
public String readTag(Tag tag) {
MifareUltralight mifare = MifareUltralight.get(tag);
try {
mifare.connect();
byte[] payload = mifare.readPages(4);
return new String(payload, Charset.forName("US-ASCII"));
} catch (IOException e) {
Log.e(TAG, "IOException while writing MifareUltralight
message...", e);
} finally {
if (mifare != null) {
try {
mifare.close();
}
catch (IOException e) {
Log.e(TAG, "Error closing tag...", e);
}
}
}
return null;
}
}
</pre>
</pre>
<h2 id="foreground-dispatch">Using the Foreground Dispatch System</h2>
<p>The foreground dispatch system allows an activity to intercept an intent and claim
priority over other activities that handle the same intent. Using this system involves
constructing a few data structures for the Android system to be able to send the appropriate
intents to your application. To enable the foreground dispatch system:</p>
<ol>
<li>Add the following code in the <code>onCreate()</code> method of your activity:
<ol type="a">
<li>Create a {@link android.app.PendingIntent} object so the Android system can populate it
with the details of the tag when it is scanned.
<pre>
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
</pre>
</li>
<li>Declare intent filters to handle the intents that you want to intercept. The foreground
dispatch system checks the specified intent filters with the intent that is received when
the device scans a tag. If it matches, then your application handles the intent. If it does
not match, the foreground dispatch system falls back to the intent dispatch system.
Specifying a <code>null</code> array of intent filters and technology filters, specifies
that you want to filter for all tags that fallback to the <code>TAG_DISCOVERED</code>
intent. The code snippet below handles all MIME types for <code>NDEF_DISCOVERED</code>. You
should only handle the ones that you need.
<pre>
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[] {ndef, };
</pre>
</li>
<li>Set up an array of tag technologies that your application wants to handle. Call the
<code>Object.class.getName()</code> method to obtain the class of the technology that you
want to support.
<pre>
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
</pre>
</li>
</ol>
</li>
<li>Override the following activity lifecycle callbacks and add logic to enable and disable the
foreground dispatch when the activity loses ({@link android.app.Activity#onPause onPause()})
and regains ({@link android.app.Activity#onResume onResume()}) focus. {@link
android.nfc.NfcAdapter#enableForegroundDispatch enableForegroundDispatch()} must be called from
the main thread and only when the activity is in the foreground (calling in {@link
android.app.Activity#onResume onResume()} guarantees this). You also need to implement the {@link
android.app.Activity#onNewIntent onNewIntent} callback to process the data from the scanned NFC
tag.</li>
<pre>
public void onPause() {
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
public void onNewIntent(Intent intent) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//do something with tagFromIntent
}
</pre>
</li>
</ol>
<p>See the <a href=
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html">
ForegroundDispatch</a> sample from API Demos for the complete sample.</p>

View File

@@ -1,601 +1,33 @@
page.title=Near Field Communication page.title=Near Field Communication
@jd:body @jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#api">API Overview</a></li>
<li><a href="#manifest">Declaring Android Manifest elements</a></li>
<li><a href="#dispatch">The Tag Dispatch System</a>
<ol>
<li><a href="#intent-dispatch">Using the intent dispatch system</a></li>
<li><a href="#foreground-dispatch">Using the foreground dispatch system</a></li>
</ol></li>
<li><a href="#ndef">Working with Data on NFC Tags</a></li>
<li><a href="#read">Reading an NFC Tag</a></li>
<li><a href="#write">Writing to an NFC Tag</a></li>
<li><a href="#p2p">Peer-to-Peer Data Exchange</a></li>
</ol>
</div>
</div>
<p>Near Field Communication (NFC) is a set of short-range wireless technologies, typically <p>Near Field Communication (NFC) is a set of short-range wireless technologies, typically
requiring a distance of 4cm or less. NFC operates at 13.56mhz, and at rates ranging from 106 requiring a distance of 4cm or less to initiate a connection. NFC allows you to share small
kbit/s to 848 kbit/s. NFC communication always involves an initiator and a target. The initiator payloads of data between an NFC tag and an Android-powered device, or between two Android-powered
actively generates an RF field that can power a passive target. This enables NFC targets to take devices.
very simple form factors such as tags, stickers or cards that do not require power. NFC
peer-to-peer communication is also possible, where both devices are powered.</p>
<p>Compared to other wireless technologies such as Bluetooth or WiFi, NFC provides much lower <p>Tags can range in complexity. Simple tags offer just read and write semantics, sometimes with
bandwidth and range, but enables low-cost, un-powered targets and does not require discovery or
pairing. Interactions can be initiated with just a tap.</p>
<p>An Android device with NFC hardware will typically act as an initiator when the screen is on.
This mode is also known as NFC reader/writer. It will actively look for NFC tags and start
activities to handle them. Android 2.3.3 also has some limited P2P support.</p>
<p>Tags can range in complexity, simple tags just offer read/write semantics, sometimes with
one-time-programmable areas to make the card read-only. More complex tags offer math operations, one-time-programmable areas to make the card read-only. More complex tags offer math operations,
and have cryptographic hardware to authenticate access to a sector. The most sophisticated tags and have cryptographic hardware to authenticate access to a sector. The most sophisticated tags
contain operating environments, allowing complex interactions with code executing on the tag.</p> contain operating environments, allowing complex interactions with code executing on the tag.
The data stored in the tag can also be written in a variety of formats, but many of the Android
<h2 id="api">API Overview</h2> framework APIs are based around a <a href="http://www.nfc-forum.org/">NFC Forum</a> standard
called NDEF (NFC Data Exchange Format).</p>
<p>The {@link android.nfc} package contains the high-level classes to interact with the local
device's NFC adapter, to represent discovered tags, and to use the NDEF data format.</p> <dl>
<dt><strong><a href="{@docRoot}guide/topics/nfc/nfc.html">NFC Basics</a></strong></dt>
<table> <dd>This document describes how Android handles discovered NFC tags and how it notifies
<tr> applications of data that is relevant to the application. It also goes over how to work with the
<th>Class</th> NDEF data in your applications and gives an overview of the framework APIs that support the basic
NFC feature set of Android.</dd>
<th>Description</th>
</tr> <dt><strong><a href="{@docRoot}guide/topics/nfc/advanced-nfc.html">Advanced
NFC</a></strong></dt>
<tr> <dd>This document goes over the APIs that enable use of the various tag technologies that
<td>{@link android.nfc.NfcManager}</td> Android supports. When you are not working with NDEF data, or when you are working with NDEF
data that Android cannot fully understand, you have to manually read or write to the tag in raw
<td>A high level manager class that enumerates the NFC adapters on this Android device. Since bytes using your own protocol stack. In these cases, Android provides support to detect
most Android devices only have one NFC adapter, you can just use the static helper {@link certain tag technologies and to open communication with the tag using your own protocol
android.nfc.NfcAdapter#getDefaultAdapter(Context)} for most situations.</td> stack.</dd>
</tr> </dl>
</p>
<tr>
<td>{@link android.nfc.NfcAdapter}</td>
<td>Represents the local NFC adapter. Defines the intent's used to request tag dispatch to
your activity, and provides methods to register for foreground tag dispatch and foreground
NDEF push. Foreground NDEF push is the only peer-to-peer support that is currently provided
in Android.</td>
</tr>
<tr>
<td>{@link android.nfc.NdefMessage} and {@link android.nfc.NdefRecord}</td>
<td>NDEF is an NFC Forum defined data structure, designed to efficiently store data on NFC
tags, such as text, URL's, and other MIME types. A {@link android.nfc.NdefMessage} acts as a
container for the data that you want to transmit or read. One {@link android.nfc.NdefMessage}
object contains zero or more {@link android.nfc.NdefRecord}s. Each NDEF record has a type
such as text, URL, smart poster, or any MIME data. The type of the first NDEF record in the
NDEF message is used to dispatch a tag to an activity on Android.</td>
</tr>
<tr>
<td>{@link android.nfc.Tag}</td>
<td>Represents a passive NFC target. These can come in many form factors such as a tag, card,
key fob, or even a phone doing card emulation. When a tag is discovered, a {@link
android.nfc.Tag} object is created and wrapped inside an Intent. The NFC dispatch system
sends the intent to a compatible activity using <code>startActivity()</code>. You can use the
{@link android.nfc.Tag#getTechList getTechList()} method to determine the technologies
supported by this tag and create the corresponding {@link android.nfc.tech.TagTechnology}
object with one of classes provided by {@link android.nfc.tech}.</td>
</tr>
</table>
<p>The {@link android.nfc.tech} package contains classes to query properties and perform I/O
operations on a tag. The classes are divided to represent different NFC technologies that can be
available on a Tag:</p>
<table>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td>{@link android.nfc.tech.TagTechnology}</td>
<td>The interface that all tag technology classes must implement.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcA}</td>
<td>Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcB}</td>
<td>Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcF}</td>
<td>Provides access to NFC-F (JIS 6319-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcV}</td>
<td>Provides access to NFC-V (ISO 15693) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.IsoDep}</td>
<td>Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.Ndef}</td>
<td>Provides access to NDEF data and operations on NFC tags that have been formatted as
NDEF.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NdefFormatable}</td>
<td>Provides a format operations for tags that may be NDEF formattable.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareClassic}</td>
<td>Provides access to MIFARE Classic properties and I/O operations, if this Android device
supports MIFARE.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareUltralight}</td>
<td>Provides access to MIFARE Ultralight properties and I/O operations, if this Android
device supports MIFARE.</td>
</tr>
</table>
<h2 id="manifest">Declaring Android Manifest elements</h2>
<p>Before you can access a device's NFC hardware and properly handle NFC intents, declare these
items in your <code>AndroidManifest.xml</code> file:</p>
<ol>
<li>The NFC <code>&lt;uses-permission&gt;</code> element to access the NFC hardware:
<pre>
&lt;uses-permission android:name="android.permission.NFC" /&gt;
</pre>
</li>
<li>The minimum SDK version that your application can support. API level 9 only supports
limited tag dispatch via {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}, and only gives
access to NDEF messages via the {@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES} extra. No
other tag properties or I/O operations are accessible. You probably want to use API level 10
which includes comprehensive reader/writer support.
<pre class="pretty-print">
&lt;uses-sdk android:minSdkVersion="10"/&gt;
</pre>
</li>
<li>The uses-feature element so that your application can show up in the Android Market for
devices that have NFC hardware:
<pre>
&lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&gt;
</pre>
</li>
<li>The NFC intent filter to tell the Android system your Activity can handle NFC data. Specify
one or more of these three intent filters:
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;data android:mimeType="<em>mime/type</em>" /&gt;
&lt;/intent-filter&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TECH_DISCOVERED"/&gt;
&lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/<em>nfc_tech_filter</em>.xml" /&gt;
&lt;/intent-filter&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TAG_DISCOVERED"/&gt;
&lt;/intent-filter&gt;
</pre>
<p>The three intent filters are prioritized and behave in specific ways. Declare only the
ones that your Activity needs to handle. For more information on how to handle these filters,
see the section about <a href="#dispatch">The Tag Dispatch System</a>.</p>
</li>
</ol>
<p>View the <a href=
"../../../resources/samples/NFCDemo/AndroidManifest.html">AndroidManifest.xml</a> from the
NFCDemo sample to see a complete example.</p>
<h2 id="dispatch">The Tag Dispatch System</h2>
<p>When an Android device scans an NFC tag, the desired behavior is to have the most appropriate
Activity handle the intent without asking the user what application to use. Because devices scan
NFC tags at a very short range, it is likely that making users manually select an Activity forces
them to move the device away from the tag and break the connection. You should develop your
Activity to only handle the NFC tags that your Activity cares about to prevent the Activity
Chooser from appearing. Android provides two systems to help you correctly identify an NFC tag
that your Activity should handle: the Intent dispatch system and the foreground Activity dispatch
system.</p>
<p>The intent dispatch system checks the intent filters of all the Activities along with the
types of data that the Activities support to find the best Activity that can handle the NFC tag.
If multiple Activities specify the same intent filter and data to handle, then the Activity
Chooser is presented to the user as a last resort.</p>
<p>The foreground dispatch system allows an Activity application to override the intent dispatch
system and have priority when an NFC tag is scanned. The Activity handling the request must be
running in the foreground of the device. When an NFC tag is scanned and matches the intent and
data type that the foreground dispatch Activity defines, the intent is immediately sent to the
Activity even if another Activity can handle the intent. If the Activity cannot handle the
intent, the foreground dispatch system falls back to the intent dispatch system.</p>
<h3 id="intent-dispatch">Using the intent dispatch system</h3>
<p>The intent dispatch system specifies three intents that each have a priority. The intents that
start when a device scans a tag depend on the type of tag scanned. In general, the intents are
started in the following manner:</p>
<ul>
<li>
<code>android.nfc.action.NDEF_DISCOVERED</code>: This intent starts when a tag that contains
an NDEF payload is scanned. This is the highest priority intent. The Android system does not
let you specify this intent generically to handle all data types. You must specify
<code>&lt;data&gt;</code> elements in the <code>AndroidManifest.xml</code> along with this
intent to correctly handle NFC tags that start this intent. For example, to handle a
<code>NDEF_DISCOVERED</code> intent that contains plain text, specify the following filter in
your <code>AndroidManifest.xml</code> file:
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;data android:mimeType="text/plain" /&gt;
&lt;/intent-filter&gt;
</pre>
<p>If the <code>NDEF_DISCOVERED</code> intent is started, the <code>TECH_DISCOVERED</code>
and <code>TAG_DISCOVERED</code> intents are not started. This intent does not start if an
unknown tag is scanned or if the tag does not contain an NDEF payload.</p>
</li>
<li><code>android.nfc.action.TECH_DISCOVERED</code>: If the <code>NDEF_DISCOVERED</code> intent
does not start or is not filtered by any Activity on the device, this intent starts if the tag
is known. The <code>TECH_DISCOVERED</code> intent requires that you specify the technologies
that you want to support in an XML resource file. For more information, see the section about
<a href="#technology-resources">Specifying tag technologies to handle</a>.</li>
<li><code>android.nfc.action.TAG_DISCOVERED</code>: This intent starts if no Activities handle
the <code>NDEF_DISCOVERED</code> and <code>TECH_DISCOVERED</code> intents or if the tag that is
scanned is unknown.</li>
</ul>
<h4 id="tech">Specifying tag technologies to handle</h4>
<p>If your Activity declares the <code>android.nfc.action.TECH_DISCOVERED</code> intent in your
<code>AndroidManifest.xml</code> file, you must create an XML resource file that specifies the
technologies that your Activity supports within a <code>tech-list</code> set. Your Activity is
considered a match if a <code>tech-list</code> set is a subset of the technologies that are
supported by the tag, which you can obtain by calling {@link android.nfc.Tag#getTechList
getTechList()}.</p>
<p>For example, if the tag that is scanned supports MifareClassic, NdefFormatable, and NfcA, your
<code>tech-list</code> set must specify all three, two, or one of the technologies (and nothing
else) in order for your Activity to be matched.</p>
<p>The following sample defines all of the technologies. You can remove the ones that you do not
need. Save this file (you can name it anything you wish) in the
<code>&lt;project-root&gt;/res/xml</code> folder.</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.IsoDep&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcV&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NdefFormatable&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareUltralight&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
<p>You can also specify multiple <code>tech-list</code> sets. Each of the <code>tech-list</code>
sets is considered independently, and your Activity is considered a match if any single
<code>tech-list</code> set is a subset of the technologies that are returned by {@link
android.nfc.Tag#getTechList getTechList()}. This provides <code>AND</code> and <code>OR</code>
semantics for matching technologies. The following example matches tags that can support the
NfcA and Ndef technologies or can support the NfcB and Ndef technologies:</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
<p>In your <code>AndroidManifest.xml</code> file, specify the resource file that you just created
in the <code>&lt;meta-data&gt;</code> element inside the <code>&lt;activity&gt;</code>
element like in the following example:</p>
<pre>
&lt;activity&gt;
...
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TECH_DISCOVERED"/&gt;
&lt;/intent-filter&gt;
&lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" /&gt;
...
&lt;/activity&gt;
</pre>
<h3 id="foreground-dispatch">Using the foreground dispatch system</h3>
<p>The foreground dispatch system allows an Activity to intercept an intent and claim priority
over other Activities that handle the same intent. The system is easy to use and involves
constructing a few data structures for the Android system to be able to send the appropriate
intents to your application. To enable the foreground dispatch system:</p>
<ol>
<li>Add the following code in the onCreate() method of your Activity:
<ol type="a">
<li>Create a {@link android.app.PendingIntent} object so the Android system can populate it
with the details of the tag when it is scanned
<pre>
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
</pre>
</li>
<li>Declare intent filters to handle the intents that you want to intercept. The foreground
dispatch system checks the specified intent filters with the intent that is received when
the device scans a tag. If they match, then your application handles the intent. If it does
not match, the foreground dispatch system falls back to the intent dispatch system.
Specifying a <code>null</code> array of intent filters and for the technology filters, you
receive a <code>TAG_DISCOVERED</code> intent for all tags discovered. Note that the snippet
below handles all MIME types. You should only handle the ones that you need.
<pre>
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[] {
ndef,
};
</pre>
</li>
<li>Set up an array of tag technologies that your application wants to handle. Call the
<code>Object.class.getName()</code> method to obtain the class of the technology that you
want to support.
<pre>
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
</pre>
</li>
</ol>
</li>
<li>Override the following Activity lifecycle callbacks and add logic to enable and disable the
foreground dispatch when the Activity loses ({@link android.app.Activity#onPause onPause()})
and regains ({@link android.app.Activity#onResume onResume()}) focus. {@link
android.nfc.NfcAdapter#enableForegroundDispatch} must be called from the main thread and only
when the activity is in the foreground (calling in {@link android.app.Activity#onResume
onResume()} guarantees this). You also need to implement the {@link
android.app.Activity#onNewIntent onNewIntent} callback to process the data from the scanned NFC
tag.
<pre>
public void onPause() {
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
public void onNewIntent(Intent intent) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//do something with tagFromIntent
}
</pre>
</li>
</ol>
<p>See the <a href=
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html">ForegroundDispatch</a>
sample from API Demos for the complete sample.</p>
<h2 id="ndef">Working with Data on NFC Tags</h2>
<p>Data on NFC tags are encoded in raw bytes, so you must convert the bytes to something human
readable if you are presenting the data to the user. When writing to NFC tags, you must write
them in bytes as well. Android provides APIs to help write messages that conform to the NDEF
standard, which was developed by the <a href="http://www.nfc-forum.org/specs/">NFC Forum</a> to
standardized data on tags. Using this standard ensures that your data will be supported by all
Android NFC devices if you are writing to tags. However, many tag technologies use their own
standard for storing data and are supported by Android as well, but you have to implement your
own protocol stack to read and write to these tags. You can find a full list of the supported
technologies in {@link android.nfc.tech} and an overview of the technologies in the {@link
android.nfc.tech.TagTechnology} interface. This section is a brief overview of how to work with
NDEF messages in the context of the Android system. It is not meant to be a complete discussion
of the NDEF specification, but highlights the main things that you need to be aware of when
working with NDEF messages in Android.</p>
<p>To facilitate working with NDEF messages, Android provides the {@link android.nfc.NdefRecord}
and {@link android.nfc.NdefMessage} to encapsulate the raw bytes that represent NDEF messages. An
{@link android.nfc.NdefMessage} is the container for zero or more {@link
android.nfc.NdefRecord}s. Each {@link android.nfc.NdefRecord} has its own unique type name
format, record type, and ID to distinguish them from other records within the same {@link
android.nfc.NdefMessage}. You can store different types of records of varying length in a single
{@link android.nfc.NdefMessage}. The size constraint of the NFC tag determines how big your
{@link android.nfc.NdefMessage} can be.</p>
<p>Tags that support the {@link android.nfc.tech.Ndef} and {@link
android.nfc.tech.NdefFormatable} technologies return and accept {@link android.nfc.NdefMessage}
objects as parameters for read and write operations. You need to create your own logic to read
and write bytes for other tag technologies in {@link android.nfc.tech}.</p>
<p>You can download technical specifications for different types of NDEF message standards, such
as plain text and Smart Posters, at the <a href="http://www.nfc-forum.org/specs/">NFC Forum</a>
website. The NFCDemo sample application also declares sample <a href=
"{@docRoot}resources/samples/NFCDemo/src/com/example/android/nfc/simulator/MockNdefMessages.html">
plain text and SmartPoster NDEF messages.</a></p>
<h2 id="read">Reading an NFC Tag</h2>
<p>When a device comes in proximity to an NFC tag, the appropriate intent is started on the
device, notifying interested applications that a NFC tag was scanned. By previously declaring the
appropriate intent filter in your <code>AndroidManifest.xml</code> file or using foreground
dispatching, your application can request to handle the intent.</p>
<p>The following method (slightly modified from the NFCDemo sample application), handles the
<code>TAG_DISCOVERED</code> intent and iterates through an array obtained from the intent that
contains the NDEF payload:</p>
<pre>
NdefMessage[] getNdefMessages(Intent intent) {
// Parse the intent
NdefMessage[] msgs = null;
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i &lt; rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
else {
// Unknown tag type
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
msgs = new NdefMessage[] {msg};
}
}
else {
Log.e(TAG, "Unknown intent " + intent);
finish();
}
return msgs;
}
</pre>
<p>Keep in mind that the data that the device reads is in bytes, so you must implement your own
logic if you need to present the data in a readable format to the user. The classes in
<code>com.example.android.nfc.record</code> of the NFCDemo sample show you how to parse some
common types of NDEF messages such as plain text or a SmartPoster.</p>
<h2 id="write">Writing to an NFC Tag</h2>
<p>Writing to an NFC tag involves constructing your NDEF message in bytes and using the
appropriate tag technology for the tag that you are writing to. The following code sample shows
you how to write a simple text message to a {@link android.nfc.tech.NdefFormatable} tag:</p>
<pre>
NdefFormatable tag = NdefFormatable.get(t);
Locale locale = Locale.US;
final byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);
String text = "Tag, you're it!";
final byte[] textBytes = text.getBytes(Charsets.UTF_8);
final int utfBit = 0;
final char status = (char) (utfBit + langBytes.length);
final byte[] data = Bytes.concat(new byte[] {(byte) status}, langBytes, textBytes);
NdefRecord record = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
try {
NdefRecord[] records = {text};
NdefMessage message = new NdefMessage(records);
tag.connect();
tag.format(message);
}
catch (Exception e){
//do error handling
}
</pre>
<h2 id="p2p">Peer-to-Peer Data Exchange</h2>
<p>Support for simple peer-to-peer data exchange is supported by the foreground push feature,
which is enabled with the {@link android.nfc.NfcAdapter#enableForegroundNdefPush} method. To use
this feature:</p>
<ul>
<li>The Activity that is pushing the data must be in the foreground</li>
<li>You must encapsulate the data that you are sending in an {@link android.nfc.NdefMessage}
object</li>
<li>The NFC device that is receiving the pushed data (the scanned device) must support the
<code>com.android.npp</code> NDEF push protocol, which is optional for Android devices.</li>
</ul>
<p class="note">If your Activity enables the foreground push feature and is in the foreground,
the standard intent dispatch system is disabled. However, if your Activity also enables
foreground dispatching, then it can still scan tags that match the intent filters set in the
foreground dispatching.</p>
<p>To enable foreground dispatching:</p>
<ol>
<li>Create an NdefMessage that contains the NdefRecords that you want to push onto the other
device.</li>
<li>Implement the {@link android.app.Activity#onResume onResume()} and {@link
android.app.Activity#onPause onPause()} callbacks in your Activity to appropriately handle the
foreground pushing lifecycle. You must call {@link
android.nfc.NfcAdapter#enableForegroundNdefPush} from the main thread and only when the
activity is in the foreground (calling in {@link android.app.Activity#onResume onResume()}
guarantees this).
<pre>
public void onResume() {
super.onResume();
if (mAdapter != null)
mAdapter.enableForegroundNdefPush(this, myNdefMessage);
}
public void onPause() {
super.onPause();
if (mAdapter != null)
mAdapter.disableForegroundNdefPush(this);
}
</pre>
</li>
</ol>
<p>When the Activity is in the foreground, you can now tap the device to another device and push
the data to it. See the <a href=
"../../../resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundNdefPush.html">ForegroundNdefPush</a>
sample in API Demos for a simple example of peer-to-peer data exchange.</p>

View File

@@ -0,0 +1,922 @@
page.title=NFC Basics
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#tag-dispatch">The Tag Dispatch System</a>
<ol>
<li><a href="#ndef">How NFC tags are mapped to MIME types and URIs</a></li>
<li><a href="#dispatching">How NFC Tags are Dispatched to Applications</a></li>
</ol>
</li>
<li><a href="#filtering-intents">Filtering for Intents</a>
<ol>
<li><a href="#ndef-disc">ACTION_NDEF_DISCOVERED</a></li>
<li><a href="#tech-disc">ACTION_TECH_DISCOVERED</a></li>
<li><a href="#tag-disc">ACTION_TAG_DISCOVERED</a></li>
<li><a href="#obtain-info">Obtaining information from intents</a></li>
</ol>
</li>
<li><a href="#creating-records">Creating Common Types of NDEF Records</a>
<ol>
<li><a href="#abs-uri">TNF_ABSOLUTE_URI</a></li>
<li><a href="#mime">TNF_MIME_MEDIA</a></li>
<li><a href="#well-known-text">TNF_WELL_KNOWN with RTD_TEXT</a></li>
<li><a href="#well-known-uri">TNF_WELL_KNOWN with RTD_URI</a></li>
<li><a href="#ext-type">TNF_EXTERNAL_TYPE</a></li>
<li><a href="#aar">Android Application Records</a></li>
</ol>
</li>
<li><a href="#p2p">Beaming NDEF Messages to Other Devices</a></li>
</ol>
</div>
</div>
<p>This document describes the basic NFC tasks you perform in Android. It explains how to send and
receive NFC data in the form of NDEF messages and describes the Android framework APIs that support
these features. For more advanced topics, including a discussion of working with non-NDEF data,
see <a href="{@docRoot}guide/topics/nfc/advanced-nfc.html">Advanced NFC</a>.</p>
<p>There are two major uses cases when working with NDEF data and Android:</p>
<ul>
<li>Reading NDEF data from an NFC tag</li>
<li>Beaming NDEF messages from one device to another with <a href="#p2p">Android
Beam&trade;</a></li>
</ul>
<p>Reading NDEF data from an NFC tag is handled with the <a href="#tag-dispatch">tag dispatch
system</a>, 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 <a href="#filtering-intents">declare an intent filter</a> and
request to handle the data.</p>
<p>The Android Beam&trade; feature allows a device to push an NDEF message onto
another device by physically tapping the devices together. This interaction provides an easier way
to send data than other wireless technologies like Bluetooth, because with NFC, no manual device
discovery or pairing is required. The connection is automatically started when two devices come
into range. Android Beam is available through a set of NFC APIs, so any application can transmit
information between devices. For example, the Contacts, Browser, and YouTube applications use
Android Beam to share contacts, web pages, and videos with other devices.
</p>
<h2 id="tag-dispatch">The Tag Dispatch System</h2>
<p>Android-powered devices are usually looking for NFC tags when the screen
is unlocked, unless NFC is disabled in the device's Settings menu.
When an Android-powered device discovers an NFC tag, the desired behavior
is to have the most appropriate activity handle the intent without asking the user what application
to use. Because devices scan NFC tags at a very short range, it is likely that making users manually
select an activity would force them to move the device away from the tag and break the connection.
You should develop your activity to only handle the NFC tags that your activity cares about to
prevent the Activity Chooser from appearing.</p>
<p>To help you with this goal, Android provides a special tag dispatch system that analyzes scanned
NFC tags, parses them, and tries to locate applications that are interested in the scanned data. It
does this by:</p>
<ol>
<li>Parsing the NFC tag and figuring out the MIME type or a URI that identifies the data payload
in the tag.</li>
<li>Encapsulating the MIME type or URI and the payload into an intent. These first two
steps are described in <a href="#ndef">How NFC tags are mapped to MIME types and URIs</a>.</li>
<li>Starts an activity based on the intent. This is described in
<a href="#dispatching">How NFC Tags are Dispatched to Applications</a>.</li>
</ol>
<h3 id="ndef">How NFC tags are mapped to MIME types and URIs</h3>
<p>Before you begin writing your NFC applications, it is important to understand the different
types of NFC tags, how the tag dispatch system parses NFC tags, and the special work that the tag
dispatch system does when it detects an NDEF message. NFC tags come in a
wide array of technologies and can also have data written to them in many different ways.
Android has the most support for the NDEF standard, which is defined by the <a
href="http://www.nfc-forum.org/home">NFC Forum</a>.
</p>
<p>NDEF data is encapsulated inside a message ({@link android.nfc.NdefMessage}) that contains one
or more records ({@link android.nfc.NdefRecord}). Each NDEF record must be well-formed according to
the specification of the type of record that you want to create. Android
also supports other types of tags that do not contain NDEF data, which you can work with by using
the classes in the {@link android.nfc.tech} package. To learn more
about these technologies, see the <a href="{@docRoot}guide/topics/nfc/advanced-nfc.html">Advanced
NFC</a> topic. Working with these other types of tags involves
writing your own protocol stack to communicate with the tags, so we recommend using NDEF when
possible for ease of development and maximum support for Android-powered devices.
</p>
<p class="note"><strong>Note:</strong>
To download complete NDEF specifications, go to the <a
href="http://www.nfc-forum.org/specs/spec_license">NFC Forum Specification Download</a> site and see
<a href="#creating-records">Creating common types of NDEF records</a> for examples of how to
construct NDEF records. </p>
<p>Now that you have some background in NFC tags, the following sections describe in more detail how
Android handles NDEF formatted tags. When an Android-powered device scans an NFC tag containing NDEF
formatted data, it parses the message and tries to figure out the data's MIME type or identifying
URI. To do this, the system reads the first {@link android.nfc.NdefRecord} inside the {@link
android.nfc.NdefMessage} to determine how to interpret the entire NDEF message (an NDEF message can
have multiple NDEF records). In a well-formed NDEF message, the first {@link android.nfc.NdefRecord}
contains the following fields:
<dl>
<dt><strong>3-bit TNF (Type Name Format)</strong></dt>
<dd>Indicates how to interpret the variable length type field. Valid values are described in
described in <a href="#table1">Table 1</a>.</dd>
<dt><strong>Variable length type</strong></dt>
<dd>Describes the type of the record. If using {@link android.nfc.NdefRecord#TNF_WELL_KNOWN}, use
this field to specify the Record Type Definition (RTD). Valid RTD values are described in <a
href="#table2">Table 2</a>.</dd>
<dt><strong>Variable length ID</strong></dt>
<dd>A unique identifier for the record. This field is not used often, but
if you need to uniquely identify a tag, you can create an ID for it.</dd>
<dt><strong>Variable length payload</strong></dt>
<dd>The actual data payload that you want to read or write. An NDEF
message can contain multiple NDEF records, so don't assume the full payload is in the first NDEF
record of the NDEF message.</dd>
</dl>
<p>The tag dispatch system uses the TNF and type fields to try to map a MIME type or URI to the
NDEF message. If successful, it encapsulates that information inside of a {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} intent along with the actual payload. However, there
are cases when the tag dispatch system cannot determine the type of data based on the first NDEF
record. This happens when the NDEF data cannot be mapped to a MIME type or URI, or when the
NFC tag does not contain NDEF data to begin with. In such cases, a {@link
android.nfc.Tag} object that has information about the tag's technologies and the payload are
encapsulated inside of a {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent instead.</p>
<p>
<a href="#table1">Table 1.</a> describes how the tag dispatch system maps TNF and type
fields to MIME types or URIs. It also describes which TNFs cannot be mapped to a MIME type or URI.
In these cases, the tag dispatch system falls back to
{@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.
<p>For example, if the tag dispatch system encounters a record of type {@link
android.nfc.NdefRecord#TNF_ABSOLUTE_URI}, it maps the variable length type field of that record
into a URI. The tag dispatch system encapsulates that URI in the data field of an {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} intent along with other information about the tag,
such as the payload. On the other hand, if it encounters a record of type {@link
android.nfc.NdefRecord#TNF_UNKNOWN}, it creates an intent that encapsulates the tag's technologies
instead.</p>
<p class="table-caption" id="table1">
<strong>Table 1.</strong> Supported TNFs and their mappings</p>
<table id="mappings">
<tr>
<th>Type Name Format (TNF)</th>
<th>Mapping</th>
</tr>
<tr>
<td>{@link android.nfc.NdefRecord#TNF_ABSOLUTE_URI}</td>
<td>URI based on the type field.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_EMPTY}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_EXTERNAL_TYPE}</td>
<td>URI based on the URN in the type field. The URN is encoded into the NDEF type field in
a shortened form: <code><em>&lt;domain_name&gt;:&lt;service_name&gt;</em></code>.
Android maps this to a URI in the form:
<code>vnd.android.nfc://ext/<em>&lt;domain_name&gt;:&lt;service_name&gt;</em></code>.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_MIME_MEDIA}</td>
<td>MIME type based on the type field.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_UNCHANGED}</td>
<td>Invalid in the first record, so falls back to
{@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_UNKNOWN}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#TNF_WELL_KNOWN}</td>
<td>MIME type or URI depending on the Record Type Definition (RTD), which you set in the
type field. See <a href="#well_known">Table 2.</a> for more information on
available RTDs and their mappings.</td>
</tr>
</table>
<p class="table-caption" id="table2">
<strong>Table 2.</strong> Supported RTDs for TNF_WELL_KNOWN and their
mappings</p>
<table id="well-known">
<tr>
<th>Record Type Definition (RTD)</th>
<th>Mapping</th>
</tr>
<tr>
<td>{@link android.nfc.NdefRecord#RTD_ALTERNATIVE_CARRIER}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_HANDOVER_CARRIER}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_HANDOVER_REQUEST}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_HANDOVER_SELECT}</td>
<td>Falls back to {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_SMART_POSTER}</td>
<td>URI based on parsing the payload.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_TEXT}</td>
<td>MIME type of <code>text/plain</code>.</td>
</tr>
<td>{@link android.nfc.NdefRecord#RTD_URI}</td>
<td>URI based on payload.</td>
</tr>
</table>
<h3 id="dispatching">How NFC Tags are Dispatched to Applications</h3>
<p>When the tag dispatch system is done creating an intent that encapsulates the NFC tag and its
identifying information, it sends the intent to an interested application that
filters for the intent. If more than one application can handle the intent, the Activity Chooser
is presented so the user can select the Activity. The tag dispatch system defines three intents,
which are listed in order of highest to lowest priority:</p>
<ol>
<li>
{@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}: This intent is used to start an
Activity when a tag that contains an NDEF payload is scanned and is of a recognized type. This is
the highest priority intent, and the tag dispatch system tries to start an Activity with this
intent before any other intent, whenever possible.
</li>
<li>{@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}: If no activities register to
handle the {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}
intent, the tag dispatch system tries to start an application with this intent. This
intent is also directly started (without starting {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} first) if the tag that is scanned
contains NDEF data that cannot be mapped to a MIME type or URI, or if the tag does not contain NDEF
data but is of a known tag technology.
</li>
<li>{@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}: This intent is started
if no activities handle the {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} or {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}
intents.</li>
</ol>
<p>The basic way the tag dispatch system works is as follows:</p>
<ol>
<li>Try to start an Activity with the intent that was created by the tag dispatch system
when parsing the NFC tag (either
{@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} or {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}).</li>
<li>If no activities filter for that intent, try to start an Activity with the next
lowest priority intent (either {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} or {@link
android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}) until an application filters for the
intent or until the tag dispatch system tries all possible intents.</li>
<li>If no applications filter for any of the intents, do nothing.</li>
</ol>
<img src="{@docRoot}images/nfc_tag_dispatch.png" />
<p class="figure"><strong>Figure 1. </strong> Tag Dispatch System</p>
<p>Whenever possible, work with NDEF messages and the {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} intent, because it is the most specific out of
the three. This intent allows you to start your application at a more appropriate time than the
other two intents, giving the user a better experience.</p>
<h2 id="manifest">Requesting NFC Access in the Android Manifest</h2>
<p>Before you can access a device's NFC hardware and properly handle NFC intents, declare these
items in your <code>AndroidManifest.xml</code> file:</p>
<ul>
<li>The NFC <code>&lt;uses-permission&gt;</code> element to access the NFC hardware:
<pre>
&lt;uses-permission android:name="android.permission.NFC" /&gt;
</pre>
</li>
<li>The minimum SDK version that your application can support. API level 9 only supports
limited tag dispatch via {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}, and only gives
access to NDEF messages via the {@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES} 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.
<pre class="pretty-print">
&lt;uses-sdk android:minSdkVersion="10"/&gt;
</pre>
</li>
<li>The <code>uses-feature</code> element so that your application shows up in the Android
Market only for devices that have NFC hardware:
<pre>
&lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&gt;
</pre>
<p>If your application uses NFC functionality, but that functionality is not crucial to your
application, you can omit the <code>uses-feature</code> element and check for NFC avalailbility at
runtime by checking to see if {@link android.nfc.NfcAdapter#getDefaultAdapter getDefaultAdapter()}
is <code>null</code>.</p>
</li>
</ul>
<h2 id="filtering-intents">Filtering for NFC Intents</h2>
<p>To start your application when an NFC tag that you want to handle is scanned, your application
can filter for one, two, or all three of the NFC intents in the Android manifest. However, you
usually want to filter for the {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} intent for the
most control of when your application starts. The {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent is a fallback for {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} when no applications filter for
{@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} or for when the payload is not
NDEF. Filtering for {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} is usually too general of a
category to filter on. Many applications will filter for {@link
android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} or {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} before {@link
android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}, so your application has a low probability of
starting. {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} is only available as a last resort
for applications to filter for in the cases where no other applications are installed to handle the
{@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} or {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED}intent.</p>
<p>Because NFC tag deployments vary and are many times not under your control, this is not always
possible, which is why you can fallback to the other two intents when necessary. When you have
control over the types of tags and data written, it is recommended that you use NDEF to format your
tags. The following sections describe how to filter for each type of intent.</p>
<h3 id="ndef-disc">ACTION_NDEF_DISCOVERED</h3>
<p>
To filter for {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} intents, declare the
intent filter along with the type of data that you want to filter for. The
following example filters for {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}
intents with a MIME type of <code>text/plain</code>:
</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;category android:name="android.intent.category.DEFAULT"/&gt;
&lt;data android:mimeType="text/plain" /&gt;
&lt;/intent-filter&gt;
</pre>
<p>The following example filters for a URI in the form of
<code>http://developer.android.com/index.html</code>.
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;category android:name="android.intent.category.DEFAULT"/&gt;
&lt;data android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html" />
&lt;/intent-filter&gt;
</pre>
<h3 id="tech-disc">ACTION_TECH_DISCOVERED</h3>
<p>If your activity filters for the {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent,
you must create an XML resource file that specifies the technologies that your activity supports
within a <code>tech-list</code> set. Your activity is
considered a match if a <code>tech-list</code> set is a subset of the technologies that are
supported by the tag, which you can obtain by calling {@link android.nfc.Tag#getTechList
getTechList()}.</p>
<p>For example, if the tag that is scanned supports MifareClassic, NdefFormatable, and NfcA, your
<code>tech-list</code> set must specify all three, two, or one of the technologies (and nothing
else) in order for your activity to be matched.</p>
<p>The following sample defines all of the technologies. You can remove the ones that you do not
need. Save this file (you can name it anything you wish) in the
<code>&lt;project-root&gt;/res/xml</code> folder.</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.IsoDep&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcV&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NdefFormatable&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareUltralight&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
<p>You can also specify multiple <code>tech-list</code> sets. Each of the <code>tech-list</code>
sets is considered independently, and your activity is considered a match if any single
<code>tech-list</code> set is a subset of the technologies that are returned by {@link
android.nfc.Tag#getTechList getTechList()}. This provides <code>AND</code> and <code>OR</code>
semantics for matching technologies. The following example matches tags that can support the
NfcA and Ndef technologies or can support the NfcB and Ndef technologies:</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
<p>In your <code>AndroidManifest.xml</code> file, specify the resource file that you just created
in the <code>&lt;meta-data&gt;</code> element inside the <code>&lt;activity&gt;</code>
element like in the following example:</p>
<pre>
&lt;activity&gt;
...
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TECH_DISCOVERED"/&gt;
&lt;/intent-filter&gt;
&lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" /&gt;
...
&lt;/activity&gt;
</pre>
<p>For more information about working with tag technologies and the {@link
android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent, see <a
href="{@docRoot}guide/topics/nfc/advanced-nfc.html#tag-tech">Working with Supported Tag
Technologies</a> in the Advanced NFC document.</p>
<h3 id="tag-disc">ACTION_TAG_DISCOVERED</h3>
<p>To filter for {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} use the following intent
filter:</p>
<pre>&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TAG_DISCOVERED"/&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="obtain-info">Obtaining information from intents</h3>
<p>If an activity starts because of an NFC intent, you can obtain information about the scanned NFC
tag from the intent. Intents can contain the following extras depending on the tag that was scanned:
<ul>
<li>{@link android.nfc.NfcAdapter#EXTRA_TAG} (required): A {@link android.nfc.Tag} object
representing the scanned tag.</li>
<li>{@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES} (optional): An array of NDEF messages
parsed from the tag. This extra is mandatory on {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED
intents.</li>
<li>{@link android.nfc.NfcAdapter#EXTRA_ID} (optional): The low-level ID of the tag.</li></ul>
<p>To obtain these extras, check to see if your activity was launched with one of
the NFC intents to ensure that a tag was scanned, and then obtain the extras out of the
intent. The following example checks for the {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}
intent and gets the NDEF messages from an intent extra.</p>
<pre>
public void onResume() {
super.onResume();
...
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i &lt; rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
}
//process the msgs array
}
</pre>
<p>Alternatively, you can obtain a {@link android.nfc.Tag} object from the intent, which will
contain the payload and allow you to enumerate the tag's technologies:</p>
<pre>Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);</pre>
<h2 id="creating-records">Creating Common Types of NDEF Records</h2>
<p>This section describes how to create common types of NDEF records to help you when writing to
NFC tags or sending data with Android Beam. It also describes how to create the corresponding
intent filter for the record. All of these NDEF record examples should be in the first NDEF
record of the NDEF message that you are writing to a tag or beaming.</p>
<h3 id="abs-uri">TNF_ABSOLUTE_URI</h3>
<p>Given the following {@link android.nfc.NdefRecord#TNF_ABSOLUTE_URI} NDEF record, which is
stored as the first record inside of an {@link android.nfc.NdefMessage}:</p>
<pre>
NdefRecord uriRecord = new NdefRecord(
NdefRecord.TNF_ABSOLUTE_URI ,
"http://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),
new byte[0], new byte[0]);
</pre>
<p>the intent filter would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html" /&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="mime">TNF_MIME_MEDIA</h3>
<p>Given the following {@link android.nfc.NdefRecord#TNF_MIME_MEDIA} NDEF record, which is stored as
the first record inside
of an {@link android.nfc.NdefMessage}:</p>
<pre>
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA ,
"application/com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
</pre>
<p>the intent filter would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:mimeType="application/com.example.android.beam" /&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="well-known-text">TNF_WELL_KNOWN with RTD_TEXT</h3>
<p>Given the following {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record, which is stored as
the first record inside of an {@link android.nfc.NdefMessage}:</p>
<pre>
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
byte[] textBytes = payload.getBytes(utfEncoding);
int utfBit = encodeInUtf8 ? 0 : (1 &lt;&lt; 7);
char status = (char) (utfBit + langBytes.length);
byte[] data = new byte[1 + langBytes.length + textBytes.length];
data[0] = (byte) status;
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
return record;
}
</pre>
<p>the intent filter would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:mimeType="text/plain" /&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="well-known-uri">TNF_WELL_KNOWN with RTD_URI</h3>
<p>Given the following {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record, which is stored as
the first record inside of an {@link android.nfc.NdefMessage}:</p>
<pre>
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix
byte payload[0] = 0x01; //prefixes http://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload
NdefRecord rtdUriRecord = new NdefRecord(
NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
</pre>
<p>the intent filter would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:scheme="http"
android:host="example.com"
android:pathPrefix="" /&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="ext-type">TNF_EXTERNAL_TYPE</h3>
<p>Given the following {@link android.nfc.NdefRecord#TNF_EXTERNAL_TYPE} NDEF record, which is stored
as the first record inside of an {@link android.nfc.NdefMessage}:</p>
<pre>
byte[] payload;
...
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_EXTERNAL_TYPE, "example.com:externalType", new byte[0], payload);
</pre>
<p>the intent filter would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/example.com:externalType"/&gt;
&lt;/intent-filter&gt;
</pre>
<p>Use TNF_EXTERNAL_TYPE for more generic NFC tag deployments to better support both
Android-powered and non-Android-powered devices.</p>
<p class="note"><strong>Note</strong>: URNs for {@link
android.nfc.NdefRecord#TNF_EXTERNAL_TYPE} have a canonical format of:
<code>urn:nfc:ext:example.com:externalType</code>, however the NFC Forum RTD specification
declares that the <code>urn:nfc:ext:</code> portion of the URN must be ommitted from the
NDEF record. So all you need to provide is the domain (<code>example.com</code> in the example)
and type (<code>externalType</code> in the example) separated by a colon.
When dispatching TNF_EXTERNAL_TYPE, Android converts the <code>urn:nfc:ext:example.com:externalType</code> URN to a
<code>vnd.android.nfc://ext/example.com:externalType</code> URI, which is what the intent filter in the example
declares.</p>
<h3 id="aar">Android Application Records</h3>
<p>
Introduced in Android 4.0 (API level 14), an Android Application Record (AAR) provides a stronger
certainty that your application is started when an NFC tag is scanned. An AAR has the package name
of an application embedded inside an NDEF record. You can add an AAR to any NDEF record of your NDEF message,
because Android searches the entire NDEF message for AARs. If it finds an AAR, it starts the application based
on the package name inside the AAR. If the application is not present on the device,
Android Market is launched to download the application.</p>
<p>AARs are useful if you want to prevent other applications from filtering for the same intent and
potentially handling specific tags that you have deployed. AARs are only supported at the
application level, because of the package name constraint, and not at the Activity level as with
intent filtering. If you want to handle an intent at the Activity level, <a
href="filtering-intents">use intent filters</a>.
</p>
<p>If a tag contains an AAR, the tag dispatch system dispatches in the following manner:</p>
<ol>
<li>Try to start an Activity using an intent filter as normal. If the Activity that matches
the intent also matches the AAR, start the Activity.</li>
<li>If the Activity that filters for the intent does not match the
AAR, if multiple Activities can handle the intent, or if no Activity handles the intent, start the
application specified by the AAR.</li>
<li>If no application can start with the AAR, go to the Android Market to download the
application based on the AAR.</li>
</ol>
</p>
<p class="note"><strong>Note:</strong> You can override AARs and the intent dispatch system with the <a
href="{@docRoot}guide/topics/nfc/advanced-nfc.html#foreground-dispatch">foreground dispatch
system</a>, which allows a foreground activity to have priority when an NFC tag is discovered.
With this method, the activity must be in the foreground to
override AARs and the intent dispatch system.</p>
<p>If you still want to filter for scanned tags that do not contain an AAR, you can declare
intent filters as normal. This is useful if your application is interested in other tags
that do not contain an AAR. For example, maybe you want to guarantee that your application handles
proprietary tags that you deploy as well as general tags deployed by third parties. Keep in mind
that AARs are specific to Android 4.0 devices or later, so when deploying tags, you most likely want
to use a combination of AARs and MIME types/URIs to support the widest range of devices. In
addition, when you deploy NFC tags, think about how you want to write your NFC tags to enable
support for the most devices (Android-powered and other devices). You can do this by
defining a relatively unique MIME type or URI to make it easier for applications to distinguish.
</p>
<p>Android provides a simple API to create an AAR,
{@link android.nfc.NdefRecord#createApplicationRecord createApplicationRecord()}. All you need to
do is embed the AAR anywhere in your {@link android.nfc.NdefMessage}. You do not want
to use the first record of your {@link android.nfc.NdefMessage}, unless the AAR is the only
record in the {@link android.nfc.NdefMessage}. This is because the Android
system checks the first record of an {@link android.nfc.NdefMessage} to determine the MIME type or
URI of the tag, which is used to create an intent for applications to filter. The following code
shows you how to create an AAR:</p>
<pre>
NdefMessage msg = new NdefMessage(
new NdefRecord[] {
...,
NdefRecord.createApplicationRecord("com.example.android.beam")}
</pre>
<h2 id="p2p">Beaming NDEF Messages to Other Devices</h2>
<p>Android Beam allows simple peer-to-peer data exchange between two Android-powered devices. The
application that wants to beam data to another device must be in the foreground and the device
receiving the data must not be locked. When the beaming device comes in close enough contact with a
receiving device, the beaming device displays the "Touch to Beam" UI. The user can then choose
whether or not to beam the message to the receiving device.</p>
<p class="note"><strong>Note:</strong> Foreground NDEF pushing was available at API level 10,
which provides similar functionality to Android Beam. These APIs have since been deprecated, but
are available to support older devices. See {@link android.nfc.NfcAdapter#enableForegroundNdefPush
enableForegroundNdefPush()} for more information.</p>
<p>You can enable Android Beam for your application by calling one of the two methods:</p>
<ul>
<li>{@link android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()}: Accepts an
{@link android.nfc.NdefMessage} to set as the message to beam. Automatically beams the message
when two devices are in close enough proximity.</li>
<li>{@link android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()}:
Accepts a callback that contains a
{@link android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()}
which is called when a device is in range to beam data to. The callback lets you create
the NDEF message only when necessary.</li>
</ul>
<p>An activity can only push one NDEF message at a time, so {@link
android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} takes precedence
over {@link android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()} if both are set. To use
Android Beam, the following general guidelines must be met:
</p>
<ul>
<li>The activity that is beaming the data must be in the foreground. Both devices must have
their screens unlocked.</li>
<li>You must encapsulate the data that you are beaming in an {@link android.nfc.NdefMessage}
object.</li>
<li>The NFC device that is receiving the beamed data must support the
<code>com.android.npp</code> NDEF push protocol or NFC Forum's SNEP (Simple NDEF Exchange
Protocol). The <code>com.android.npp</code> protocol is required for devices on API level 9 (Android
2.3) to API level 13 (Android 3.2). <code>com.android.npp</code> and SNEP are both required on
API level 14 (Android 4.0) and later.</li>
</li>
</ul>
<p class="note"><strong>Note:</strong> If your activity enables Android Beam and is
in the foreground, the standard intent dispatch system is disabled. However, if your activity also
enables <a href="{@docRoot}guide/topics/nfc/advanced-nfc.html#foreground-dispatch">foreground
dispatching</a>, then it can still scan tags that match the intent filters set in the foreground
dispatching.</p>
<p>To enable Android Beam:</p>
<ol>
<li>Create an {@link android.nfc.NdefMessage} that contains the {@link android.nfc.NdefRecord}s
that you want to push onto the other device.</li>
<li>Call {@link
android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()} with a {@link
android.nfc.NdefMessage} or call {@link
android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback} passing in a {@link
android.nfc.NfcAdapter.CreateNdefMessageCallback} object in the <code>onCreate()</code> method of
your activity. These methods require at least one activity that you want to enable with Android
Beam, along with an optional list of other activities to activate.
<p>In general, you normally use {@link
android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()} if your Activity only needs to
push the same NDEF message at all times, when two devices are in range to communicate. You use
{@link android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback} when your
application cares about the current context of the application and wants to push an NDEF message
depending on what the user is doing in your application.</p>
</li>
</ol>
<p>The following sample shows how a simple activity calls {@link
android.nfc.NfcAdapter.CreateNdefMessageCallback} in the <code>onCreate()</code> method of an
activity (see <a href="{@docRoot}resources/samples/AndroidBeam/index.html"></a> for the
complete sample). This example also has methods to help you create a MIME record:</p>
<pre id="code-example">
package com.example.android.beam;
import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;
public class Beam extends Activity implements CreateNdefMessageCallback {
NfcAdapter mNfcAdapter;
TextView textView;
&#064;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textView = (TextView) findViewById(R.id.textView);
// Check for available NFC Adapter
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
// Register callback
mNfcAdapter.setNdefPushMessageCallback(this, this);
}
&#064;Override
public NdefMessage createNdefMessage(NfcEvent event) {
String text = ("Beam me up, Android!\n\n" +
"Beam Time: " + System.currentTimeMillis());
NdefMessage msg = new NdefMessage(
new NdefRecord[] { createMimeRecord(
"application/com.example.android.beam", text.getBytes())
/**
* The Android Application Record (AAR) is commented out. When a device
* receives a push with an AAR in it, the application specified in the AAR
* is guaranteed to run. The AAR overrides the tag dispatch system.
* You can add it back in to guarantee that this
* activity starts when receiving a beamed message. For now, this code
* uses the tag dispatch system.
*/
//,NdefRecord.createApplicationRecord("com.example.android.beam")
});
return msg;
}
&#064;Override
public void onResume() {
super.onResume();
// Check to see that the Activity started due to an Android Beam
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
processIntent(getIntent());
}
}
&#064;Override
public void onNewIntent(Intent intent) {
// onResume gets called after this to handle the intent
setIntent(intent);
}
/**
* Parses the NDEF Message from the intent and prints to the TextView
*/
void processIntent(Intent intent) {
textView = (TextView) findViewById(R.id.textView);
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
// only one message sent during the beam
NdefMessage msg = (NdefMessage) rawMsgs[0];
// record 0 contains the MIME type, record 1 is the AAR, if present
textView.setText(new String(msg.getRecords()[0].getPayload()));
}
/**
* Creates a custom MIME type encapsulated in an NDEF record
*/
public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
return mimeRecord;
}
}
</pre>
<p>Note that this code comments out an AAR, which you can remove. If you enable the AAR, the
application specified in the AAR always receives the Android Beam message. If the application is not
present, the Android Market is started to download the application. Therefore, the following intent
filter is not technically necessary for Android 4.0 devices or later if the AAR is used:
</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;category android:name="android.intent.category.DEFAULT"/&gt;
&lt;data android:mimeType="application/com.example.android.beam"/&gt;
&lt;/intent-filter&gt;
</pre>
<p>With this intent filter, the <code>com.example.android.beam</code> application now can be started
when it scans an NFC tag or receives an Android Beam with an AAR of
type <code>com.example.android.beam</code>, or when an NDEF formatted message contains a MIME record
of type <code>application/com.example.android.beam</code>.</p>
<p>Even though AARs guarantee an application is started or downloaded, intent filters are
recommended, because they let you start an Activity of your choice in your
application instead of always starting the main Activity within the package specified by an AAR.
AARs do not have Activity level granularity. Also, because some Android-powered devices do not
support AARs, you should also embed identifying information in the first NDEF record of your NDEF
messages and filter for that as well, just in case. See <a href="#creating-records">Creating Common
Types of NDEF records</a> for more information on how to create records.
</p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB