Merge "cherrypick from master - docs: nfc updates Change-Id: Iaa782911f14b11bc896ac9ef06db2c43104d1dac" into ics-mr0
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
303
docs/html/guide/topics/nfc/advanced-nfc.jd
Normal file
303
docs/html/guide/topics/nfc/advanced-nfc.jd
Normal 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>
|
||||||
@@ -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><uses-permission></code> element to access the NFC hardware:
|
|
||||||
<pre>
|
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
|
||||||
</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">
|
|
||||||
<uses-sdk android:minSdkVersion="10"/>
|
|
||||||
</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>
|
|
||||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
|
||||||
</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>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
|
||||||
<data android:mimeType="<em>mime/type</em>" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
|
|
||||||
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
|
|
||||||
android:resource="@xml/<em>nfc_tech_filter</em>.xml" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
|
|
||||||
</intent-filter>
|
|
||||||
</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><data></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>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
|
||||||
<data android:mimeType="text/plain" />
|
|
||||||
</intent-filter>
|
|
||||||
</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><project-root>/res/xml</code> folder.</p>
|
|
||||||
<pre>
|
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
|
||||||
<tech-list>
|
|
||||||
<tech>android.nfc.tech.IsoDep</tech>
|
|
||||||
<tech>android.nfc.tech.NfcA</tech>
|
|
||||||
<tech>android.nfc.tech.NfcB</tech>
|
|
||||||
<tech>android.nfc.tech.NfcF</tech>
|
|
||||||
<tech>android.nfc.tech.NfcV</tech>
|
|
||||||
<tech>android.nfc.tech.Ndef</tech>
|
|
||||||
<tech>android.nfc.tech.NdefFormatable</tech>
|
|
||||||
<tech>android.nfc.tech.MifareClassic</tech>
|
|
||||||
<tech>android.nfc.tech.MifareUltralight</tech>
|
|
||||||
</tech-list>
|
|
||||||
</resources>
|
|
||||||
</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>
|
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
|
||||||
<tech-list>
|
|
||||||
<tech>android.nfc.tech.NfcA</tech>
|
|
||||||
<tech>android.nfc.tech.Ndef</tech>
|
|
||||||
</tech-list>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
|
||||||
<tech-list>
|
|
||||||
<tech>android.nfc.tech.NfcB</tech>
|
|
||||||
<tech>android.nfc.tech.Ndef</tech>
|
|
||||||
</tech-list>
|
|
||||||
</resources>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>In your <code>AndroidManifest.xml</code> file, specify the resource file that you just created
|
|
||||||
in the <code><meta-data></code> element inside the <code><activity></code>
|
|
||||||
element like in the following example:</p>
|
|
||||||
<pre>
|
|
||||||
<activity>
|
|
||||||
...
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
|
|
||||||
android:resource="@xml/nfc_tech_filter" />
|
|
||||||
...
|
|
||||||
</activity>
|
|
||||||
</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 < 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>
|
|
||||||
922
docs/html/guide/topics/nfc/nfc.jd
Normal file
922
docs/html/guide/topics/nfc/nfc.jd
Normal 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™</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™ 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><domain_name>:<service_name></em></code>.
|
||||||
|
Android maps this to a URI in the form:
|
||||||
|
<code>vnd.android.nfc://ext/<em><domain_name>:<service_name></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><uses-permission></code> element to access the NFC hardware:
|
||||||
|
<pre>
|
||||||
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
|
</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">
|
||||||
|
<uses-sdk android:minSdkVersion="10"/>
|
||||||
|
</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>
|
||||||
|
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||||
|
</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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
</pre>
|
||||||
|
<p>The following example filters for a URI in the form of
|
||||||
|
<code>http://developer.android.com/index.html</code>.
|
||||||
|
<pre>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<data android:scheme="http"
|
||||||
|
android:host="developer.android.com"
|
||||||
|
android:pathPrefix="/index.html" />
|
||||||
|
</intent-filter>
|
||||||
|
</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><project-root>/res/xml</code> folder.</p>
|
||||||
|
<pre>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<tech-list>
|
||||||
|
<tech>android.nfc.tech.IsoDep</tech>
|
||||||
|
<tech>android.nfc.tech.NfcA</tech>
|
||||||
|
<tech>android.nfc.tech.NfcB</tech>
|
||||||
|
<tech>android.nfc.tech.NfcF</tech>
|
||||||
|
<tech>android.nfc.tech.NfcV</tech>
|
||||||
|
<tech>android.nfc.tech.Ndef</tech>
|
||||||
|
<tech>android.nfc.tech.NdefFormatable</tech>
|
||||||
|
<tech>android.nfc.tech.MifareClassic</tech>
|
||||||
|
<tech>android.nfc.tech.MifareUltralight</tech>
|
||||||
|
</tech-list>
|
||||||
|
</resources>
|
||||||
|
</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>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<tech-list>
|
||||||
|
<tech>android.nfc.tech.NfcA</tech>
|
||||||
|
<tech>android.nfc.tech.Ndef</tech>
|
||||||
|
</tech-list>
|
||||||
|
</resources>
|
||||||
|
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<tech-list>
|
||||||
|
<tech>android.nfc.tech.NfcB</tech>
|
||||||
|
<tech>android.nfc.tech.Ndef</tech>
|
||||||
|
</tech-list>
|
||||||
|
</resources>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>In your <code>AndroidManifest.xml</code> file, specify the resource file that you just created
|
||||||
|
in the <code><meta-data></code> element inside the <code><activity></code>
|
||||||
|
element like in the following example:</p>
|
||||||
|
<pre>
|
||||||
|
<activity>
|
||||||
|
...
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
|
||||||
|
android:resource="@xml/nfc_tech_filter" />
|
||||||
|
...
|
||||||
|
</activity>
|
||||||
|
</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><intent-filter>
|
||||||
|
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</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 < 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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="http"
|
||||||
|
android:host="developer.android.com"
|
||||||
|
android:pathPrefix="/index.html" />
|
||||||
|
</intent-filter>
|
||||||
|
</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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="application/com.example.android.beam" />
|
||||||
|
</intent-filter>
|
||||||
|
</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 << 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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
</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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="http"
|
||||||
|
android:host="example.com"
|
||||||
|
android:pathPrefix="" />
|
||||||
|
</intent-filter>
|
||||||
|
</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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="vnd.android.nfc"
|
||||||
|
android:host="ext"
|
||||||
|
android:pathPrefix="/example.com:externalType"/>
|
||||||
|
</intent-filter>
|
||||||
|
</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;
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<data android:mimeType="application/com.example.android.beam"/>
|
||||||
|
</intent-filter>
|
||||||
|
</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>
|
||||||
BIN
docs/html/images/nfc_tag_dispatch.png
Normal file
BIN
docs/html/images/nfc_tag_dispatch.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Reference in New Issue
Block a user