Android NFC详解
时间:2023-01-11 04:00:00
1、NFC概览
NFC,全称是Near Field Communication,中为近场通信,又称近距离无线通信技术。使用了NFC技术设备(如移动电话)可以通过非接触式射频识别进行数据交换(RFID)通过感应读卡器、感应读卡器和点对点通信功能的集成,通过移动终端实现移动支付、电子票务、门禁、移动身份识别、防伪等应用。
2、NFC工作原理
NFC短距离高频无线电技术,NFCIP-1标准规定NFC通信距离10cm以内,运行频率13.56MHz,传输速度有106Kbit/s、212Kbit/s或者424Kbit/s三种。NFCIP-1标准的详细规定NFC本标准还定义了射频接口的传输速度、编解码方法、调制方案和帧格式NFC传输协议包括启动协议和数据交换方法。
NFC工作模式分为被动模式和主动模式。
1)被动模式
被动模式中NFC启动设备(也称为主设备)需要供电设备主设备利用供电设备的能量提供射频场,并将数据发送到NFC目标设备(也称为从设备)的传输速率为106kbps、212kbps或424kbps选一个。从设备不产生射频场,不需要供电设备,而是将主设备产生的射频场转换为电能,接收主设备发送的数据,并使用负载调制(load modulation)该技术将从设备数据以样的速度传回主设备。在这种工作模式下,被称为被动模式,因为设备不产生射频场,而是被动接收主设备产生的射频场。NFC主要设备可检测非接触式卡或NFC与目标设备建立联系。
2)主动模式
在主动模式下,当启动设备和目标设备相互发送数据时,必须主动生成射频场,因此称为主动模式,它们都需要供电设备来提供生成射频场的能量。该通信模式是平等网络通信的标准模式,可以获得非常快的连接率
3、NFC在Android上应用
近距离无线通信 (NFC) 借助近距离无线技术,是一组近距离无线技术 NFC,您可以在 NFC 标签与 Android 设备之间或两台 Android 小负荷在设备之间共享。
标签的复杂性可能不同。简单的标签只提供读写语义,有时可以使用一次性可编程区域将卡设置为只读。复杂的标签可以提供数学操作,加密硬件可以用来验证风扇区域的访问权限。最复杂的标签可以包含操作环境,允许与标签执行代码复杂互动。存储在标签中的数据也可以以多种格式编写,但许多 Android 框架 API 都基于名为 NDEF(NFC 数据交换格式)NFC Forum标准。
支持 NFC 的 Android 同时支持以下设备三种主要操作模式:
- 读取器/写入器模式:支持 NFC 读取和/或写入被动设备 NFC 标签和贴纸。
- 点对点模式:支持 NFC 设备与其他 NFC 对等设备交换数据;Android Beam 使用这种操作模式。
- 卡模拟模式:支持 NFC 设备本身充当 NFC 卡。然后,它可以通过外部 NFC 读取器(例如 NFC 访问模拟的销售终端) NFC 卡。
1)基本 NFC 任务
将 NDEF 数据与 Android 主要用例有两个:
- 从 NFC 标签读取 NDEF 数据
- 使用Android Beam?将 NDEF 消息从一台设备传输到另一台设备
从 NFC 标签读取 NDEF 数据的操作由标签调度系统处理,系统将分析发现的数据 NFC 标签,适当分类相应的数据,然后启动对分类数据感兴趣的应用程序。如果某个应用程序想处理扫描 NFC 可以声明标签 Intent 过滤器,并要求处理数据。
借助 Android Beam? 功能,设备可以 NDEF 将消息推到另一台设备上的方法是将两台设备放在一起。与蓝牙等无线技术相比,这种交互可以提供更简单的数据发送方式 NFC 无需手动找到设备并匹配。当两台设备之间的距离接近一定范围时,系统会自动开始连接。Android Beam 通过一组功能 NFC API 因此,任何应用程序都可以在设备间传输信息。例如,通讯录、浏览器和 YouTube 应用可使用 Android Beam 共享联系人信息、网页和视频。
标签调度系统
Android 屏幕解锁后,设备通常会被搜索 NFC 除非设备的设置菜单中停止使用标签 NFC 功能。在 Android 设备发现 NFC 在标签之后,的行为是最合适的 Activity 来处理该 Intent,而不是问用户应该使用哪个应用程序。
帮助你实现这一目标,Android 为分析扫描提供了一个特殊的标签调度系统 NFC 标签,分析它们,并尝试找到对扫描数据感兴趣的应用程序。标签调度系统通过以下操作实现了这些目的:
- 解析 NFC 标签并确定 MIME 类型或 URI(后者用于识别标签中的数据负载)。
- 将 MIME 类型或 URI 与负载一起包装 Intent 中。
- 根据 Intent 启动 Activity。
如何将 NFC 标签映射到 MIME 类型和 URI
在开始编写 NFC 在应用之前,请务必了解不同类型的应用程序 NFC 如何分析标签调度系统 NFC 检测到标签调度系统 NDEF 新闻后执行的特殊工作。NFC 标签涉及多种技术,数据也可以以多种不同的方式写入 NFC 标签中。Android 对 NFC Forum 定义的 NDEF 最完整的标准支持。
NDEF 数据包含一个或多个记录 (NdefRecord) 的消息 (NdefMessage) 内。每条 NDEF 记录格式必须正确,符合您想要创建的记录类型对应的规范。Android 还支持其他类型的不包括 NDEF 您可以使用数据标签 android.nfc.tech 软件包中的类处理这些标签。在处理这些其他类型的标签时,您需要通过编写自己的协议栈与标签沟通。因此,我们建议您尽可能多地使用它们 NDEF,简化发展,最大限度地支持 Android 设备。
注意:要下载完整的 NDEF 请转到规范NFC Forum 规范和应用文档网站,查看如何构建 NDEF 记录的示例。
现在,你已经知道了 NFC 以下部分将详细介绍标签的一些相关背景知识 Android 如何处理 NDEF 格式的标签。当 Android 包括设备扫描 NDEF 格式数据的 NFC 当标签时,它会分析消息并尝试确定数据 MIME 类型或标识 URI。因此,系统需要读取 NdefMessage 中的第一条 NdefRecord,确定如何解读整个 NDEF 消息(一个 NDEF 可能有很多消息 NDEF 记录)。格式正确 NDEF 第一条消息 NdefRecord 包括以下字段:
a)、3 位 TNF(类型名称格式)
表示如何解释可变长度类型的字段。 1 介绍了有效值。
b)、可变长度类型
介绍了记录的类型。如果使用, TNF_WELL_KNOWN,那么请使用此字段来指定记录类型定义 (RTD)。表 2 介绍有效 RTD 值。
c)、可变长度 ID
唯一记录的标识符。这个字段不常用,但是如果你需要标记标签,你可以为它创建它 ID。
d)、可变长度负载
您需要读取或写入实际数据负载。 NDEF 多个消息可以包含 NDEF 所以不要假设记录 NDEF 第一条消息 NDEF 记录中有完整的负载。
:
vnd.android.nfc://ext/:
基于类型字段中 URN 的 URI。URN 以缩短形式 () 编码到 NDEF 类型字段中。Android 会以如下形式将此映射到 URI:。
类型名称格式 (TNF) | 映射 |
---|---|
TNF_ABSOLUTE_URI |
基于类型字段 URI。 |
TNF_EMPTY |
回退到ACTION_TECH_DISCOVERED 。 |
TNF_EXTERNAL_TYPE | |
TNF_MIME_MEDIA |
基于类型字段的 MIME 类型。 |
TNF_UNCHANGED |
在第一条记录中无效,因此会回退到 ACTION_TECH_DISCOVERED 。 |
TNF_UNKNOWN |
回退到 ACTION_TECH_DISCOVERED 。 |
TNF_WELL_KNOWN |
MIME 类型或 URI,具体取决于您在类型字段中设置的记录类型定义 (RTD)。如需详细了解可用的 RTD 及其映射,请参阅表 2。 |
记录类型定义 (RTD) | 映射 |
---|---|
RTD_ALTERNATIVE_CARRIER |
回退到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_CARRIER |
回退到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_REQUEST |
回退到 ACTION_TECH_DISCOVERED 。 |
RTD_HANDOVER_SELECT |
回退到 ACTION_TECH_DISCOVERED 。 |
RTD_SMART_POSTER |
基于负载解析结果的 URI。 |
RTD_TEXT |
text/plain 的 MIME 类型。 |
RTD_URI |
基于负载的 URI。 |
标签调度系统使用 TNF 和类型字段来尝试将 MIME 类型或 URI 映射到 NDEF 消息。如果成功映射,它会将相关信息与实际负载一起封装到 ACTION_NDEF_DISCOVERED Intent 内。不过,在某些情况下,标签调度系统无法根据第一条 NDEF 记录来确定数据的类型。如果 NDEF 数据无法映射到 MIME 类型或 URI,或者 NFC 标签不包含 NDEF 数据,就会出现上述情况。在此类情况下,标签调度系统会转而将含有标签技术相关信息的 Tag 对象及负载封装到ACTION_TECH_DISCOVERED Intent 中。
表 1 介绍了标签调度系统如何将 TNF 和类型字段映射到 MIME 类型或 URI,还介绍了哪些 TNF 无法映射到 MIME 类型或 URI。如果无法映射,标签调度系统会回退到 ACTION_TECH_DISCOVERED。
例如,如果标签调度系统遇到 TNF_ABSOLUTE_URI 类型的记录,则会将该记录的可变长度类型字段映射到 URI 中。标签调度系统将此 URI 连同与标签有关的其他信息(如负载)一起封装在 ACTION_NDEF_DISCOVERED Intent 的数据字段中。另一方面,如果标签调度系统遇到 TNF_UNKNOWN 类型的记录,则会转而创建一个 Intent,用于封装与标签技术相关的信息。
如何将 NFC 标签分发到应用
当标签调度系统创建完用于封装 NFC 标签及其标识信息的 Intent 后,它会将该 Intent 发送给感兴趣的应用,由这些应用对其进行过滤。如果有多个应用可处理该 Intent,系统会显示 Activity 选择器,供用户选择要使用的 Activity。标签调度系统定义了三种 Intent,按优先级从高到低列出如下:
- ACTION_NDEF_DISCOVERED:如果扫描到包含 NDEF 负载的标签,并且可识别其类型,则使用此 Intent 启动 Activity。这是优先级最高的 Intent,标签调度系统会尽可能尝试使用此 Intent 启动 Activity,在行不通时才会尝试使用其他 Intent。
- ACTION_TECH_DISCOVERED:如果没有登记要处理 ACTION_NDEF_DISCOVERED Intent 的 Activity,则标签调度系统会尝试使用此 Intent 来启动应用。此外,如果扫描到的标签包含无法映射到 MIME 类型或 URI 的 NDEF 数据,或者该标签不包含 NDEF 数据,但它使用了已知的标签技术,那么也会直接启动此 Intent(无需先启动 ACTION_NDEF_DISCOVERED)。
- ACTION_TAG_DISCOVERED:如果没有处理 ACTION_NDEF_DISCOVERED 或者 ACTION_TECH_DISCOVERED Intent 的 Activity,则使用此 Intent 启动 Activity。
标签调度系统的基本工作方式如下:
- 在解析 NFC 标签(ACTION_NDEF_DISCOVERED 或 ACTION_TECH_DISCOVERED)时,尝试使用由标签调度系统创建的 Intent 启动 Activity。
- 如果不存在过滤该 Intent 的 Activity,则尝试使用下一优先级的 Intent(ACTION_TECH_DISCOVERED 或 ACTION_TAG_DISCOVERED)启动 Activity,直到应用过滤该 Intent 或者直到标签调度系统试完所有可能的 Intent。
- 如果没有应用过滤任何 Intent,则不执行任何操作。

尽可能使用 NDEF 消息和 ACTION_NDEF_DISCOVERED Intent,因为它是三种 Intent 中最具体的一种。与其他两种 Intent 相比,此 Intent 可使您在更恰当的时间启动应用,从而为用户带来更好的体验。
在 Android 清单中请求 NFC 访问权限
您必须先在 AndroidManifest.xml
文件中声明以下内容,然后才能访问设备的 NFC 硬件并正确处理 NFC Intent:
- 用于访问 NFC 硬件的 NFC
元素:
- 您的应用支持的最低 SDK 版本。API 级别 9 仅通过 ACTION_TAG_DISCOVERED 支持有限的标签调度,并且只能通过 EXTRA_NDEF_MESSAGES extra 提供对 NDEF 消息的访问权限。无法访问其他任何标签属性或 I/O 操作。API 级别 10 提供全面的读取器/写入器支持以及前台 NDEF 推送功能;API 级别 14 则提供了一种更简便的方式(即,使用 Android Beam 将 NDEF 消息推送到其他设备),同时提供了用于创建 NDEF 记录的其他便捷方法。
uses-feature
元素,以便您的应用仅在那些具备 NFC 硬件的设备的 Google Play 中显示:
如果您的应用使用 NFC 功能,但该功能对您的应用来说并不重要,您可以省略 uses-feature 元素,并在运行时通过检查 getDefaultAdapter() 是否为 null 来了解 NFC 的可用性。
过滤 NFC Intent
要在扫描到您打算处理的 NFC 标签时启动您的应用,您的应用可以在 Android 清单中过滤一个、两个或所有三个 NFC Intent。不过,您通常需要过滤 ACTION_NDEF_DISCOVERED Intent,以最有力地控制应用在何时启动。如果没有应用过滤 ACTION_NDEF_DISCOVERED,或者负载不是 NDEF,ACTION_TECH_DISCOVERED Intent 会取代 ACTION_NDEF_DISCOVERED。ACTION_TAG_DISCOVERED 通常因过于笼统而不适合过滤。许多应用会在过滤 ACTION_TAG_DISCOVERED 前过滤 ACTION_NDEF_DISCOVERED 或 ACTION_TECH_DISCOVERED,导致 您的应用启动的概率会比较低。过滤 ACTION_TAG_DISCOVERED 是应用在没有其他应用来处理 ACTION_NDEF_DISCOVERED 或 ACTION_TECH_DISCOVERED Intent 的情况下的最后一道保险。
由于 NFC 标签部署各有不同,并且很多时候它们都不由您控制,因此,ACTION_NDEF_DISCOVERED 不一定每次都可用,您可以根据需要回退到另外两种 Intent。如果您可以控制标签和写入数据的类型,建议您使用 NDEF 来设置标签的格式。以下几部分介绍了如何过滤各类 Intent。
- ACTION_NDEF_DISCOVERED
要过滤 ACTION_NDEF_DISCOVERED Intent,请声明 Intent 过滤器以及要过滤的数据类型。以下示例展示了如何过滤 MIME 类型为 text/plain 的 ACTION_NDEF_DISCOVERED Intent:
以下示例展示了如何过滤采用 https://developer.android.com/index.html
形式的 URI。
- ACTION_TECH_DISCOVERED
如果您的 Activity 过滤 ACTION_TECH_DISCOVERED Intent,您必须创建一个 XML 资源文件,用它在 tech-list 集内指定您的 Activity 所支持的技术。如果 tech-list 集是标签所支持的技术(可通过调用 getTechList() 来获取)的子集,则您的 Activity 会被视为一个匹配项。
例如,如果扫描到的标签支持 MifareClassic、NdefFormatable 和 NfcA,为了使它们与您的 Activity 匹配,您的 tech-list 集必须指定所有这三种技术,或者其中的两种或一种技术。
以下示例定义了所有技术。您可以移除自己不需要的技术。将此文件(你可以随便命名)保存到
android.nfc.tech.IsoDep
android.nfc.tech.NfcA
android.nfc.tech.NfcB
android.nfc.tech.NfcF
android.nfc.tech.NfcV
android.nfc.tech.Ndef
android.nfc.tech.NdefFormatable
android.nfc.tech.MifareClassic
android.nfc.tech.MifareUltralight
您还可以指定多个 tech-list 集。每个 tech-list 集都是独立的;如果任意一个 tech-list 集是由 getTechList() 返回的技术的子集,则您的 Activity 会被视为一个匹配项。这为匹配技术提供了 AND 和 OR 语义。以下示例展示了如何与支持 NfcA 和 Ndef 技术的标签或者支持 NfcB 和 Ndef 技术的标签相匹配:
android.nfc.tech.NfcA
android.nfc.tech.Ndef
android.nfc.tech.NfcB
android.nfc.tech.Ndef
在您的 AndroidManifest.xml
文件中,在
元素的
元素中指定您刚刚创建的资源文件,如以下示例所示:
...
...
如需详细了解如何使用标签技术和 ACTION_TECH_DISCOVERED Intent,请参阅高级 NFC 文档中的使用支持的标签技术(以后写)。
-
ACTION_TAG_DISCOVERED
要过滤 ACTION_TAG_DISCOVERED,请使用以下 Intent 过滤器:
-
从 Intent 中获取信息
如果某个 Activity 由于 NFC Intent 而启动,您可以从该 Intent 中获取有关扫描到的 NFC 标签的信息。Intent 可以包含以下 extra,具体取决于扫描到的标签:
- EXTRA_TAG(必需):一个 Tag 对象,表示扫描到的标签。
- EXTRA_NDEF_MESSAGES(可选):从标签中解析出的一组 NDEF 消息。此 extra 对于 ACTION_NDEF_DISCOVERED Intent 而言是必需的。
- EXTRA_ID(可选):标签的低级别 ID。
要获取这些 extra,请检查您的 Activity 是不是使用某个 NFC Intent 启动的,以确保已扫描到标签,然后获取 Intent 的 extra。以下示例展示了如何检查 ACTION_NDEF_DISCOVERED Intent 并从 Intent extra 获取 NDEF 消息。
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
...
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
Parcelable[] rawMessages =
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
NdefMessage[] messages = new NdefMessage[rawMessages.length];
for (int i = 0; i < rawMessages.length; i++) {
messages[i] = (NdefMessage) rawMessages[i];
}
// Process the messages array.
...
}
}
}
或者,您可以从 Intent 中获取 Tag 对象,该对象包含负载并允许您枚举标签的技术:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
创建常见类型的 NDEF 记录
本部分介绍了如何创建常见类型的 NDEF 记录,以帮助向 NFC 标签写入数据或使用 Android Beam 发送数据。从 Android 4.0(API 级别 14)开始引入平台的 createUri() 方法可帮助您自动创建 URI 记录。从 Android 4.1(API 级别 16)开始引入平台的 createExternal() 和 createMime() 可帮助您创建 MIME 和外部类型的 NDEF 记录。请尽可能使用这些辅助方法,以免在手动创建 NDEF 记录时出错。
本部分还介绍了如何为记录创建相应的 Intent 过滤器。所有这些 NDEF 记录示例都应该位于您写入标签或传输到另一设备的 NDEF 消息的第一条 NDEF 记录中。
a)、TNF_ABSOLUTE_URI
注意:建议您使用 RTD_URI 类型,而不是 TNF_ABSOLUTE_URI,因为前者更为高效。
您可以通过以下方式创建一条 TNF_ABSOLUTE_URI NDEF 记录:
NdefRecord uriRecord = new NdefRecord(
NdefRecord.TNF_ABSOLUTE_URI ,
"https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),
new byte[0], new byte[0]);
上一条 NDEF 记录的 Intent 过滤器如下所示:
b)、TNF_MIME_MEDIA
您可以通过以下方式创建一条 TNF_MIME_MEDIA NDEF 记录:
使用 createMime() 方法:
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam",
"Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
手动创建 NdefRecord:
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA ,
"application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
上一条 NDEF 记录的 Intent 过滤器如下所示:
c)、RTD 为 RTD_TEXT 的 TNF_WELL_KNOWN
您可以通过以下方式创建一条 TNF_WELL_KNOWN NDEF 记录:
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;
}
上一条 NDEF 记录的 Intent 过滤器如下所示:
d)、RTD 为 RTD_URI 的 TNF_WELL_KNOWN
您可以通过以下方式创建一条 TNF_WELL_KNOWN NDEF 记录:
使用 createUri(String) 方法:
NdefRecord rtdUriRecord1 = NdefRecord.createUri("http://example.com");
使用 createUri(Uri) 方法:
Uri uri = Uri.parse("http://example.com");
NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
手动创建 NdefRecord:
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix
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);
上一条 NDEF 记录的 Intent 过滤器如下所示:
使用 TNF_EXTERNAL_TYPE 实现更通用的 NFC 标签部署,以更好地支持 Android 设备和非 Android 设备。
注意:TNF_EXTERNAL_TYPE 的 URN 的规范格式为urn:nfc:ext:example.com:externalType
,但 NFC Forum RTD 规范包含如下声明:NDEF 记录中必须省略 URN 的 urn:nfc:ext:
部分。因此,您只需要提供域名(示例中为 example.com
)和类型(示例中为 externalType
),并通过英文冒号将两者分隔开。分发 TNF_EXTERNAL_TYPE
时,Android 会将 urn:nfc:ext:example.com:externalType
URN 转换为 vnd.android.nfc://ext/example.com:externalType
URI,也就是示例中的 Intent 过滤器声明的 URI。
e)、Android 应用记录
Android 4.0(API 级别 14)中引入了 Android 应用记录 (AAR) 功能,它可以更有力地确保在扫描到 NFC 标签时启动您的应用。AAR 在 NDEF 记录内嵌入了应用的软件包名称。您可以将 AAR 添加到 NDEF 消息的任意 NDEF 记录中,因为 Android 会在整个 NDEF 消息中搜索 AAR。如果找到 AAR,它会根据 AAR 中的软件包名称启动相应应用。如果设备上没有该应用,则会启动 Google Play,供用户下载该应用。
如果您想要阻止其他应用过滤同一 Intent,并阻止其他应用潜在地处理您已部署的特定标签,则可以使用 AAR。由于软件包名称方面的限制,AAR 仅在应用级别受支持,与 Intent 过滤一样在 Activity 级别不受支持。如果您需要在 Activity 级别处理 Intent,可使用 Intent 过滤器。
如果标签包含 AAR,标签调度系统将按以下方式执行分发:
- 尝试照常使用 Intent 过滤器启动 Activity。如果与 Intent 匹配的 Activity 也与 AAR 匹配,则启动该 Activity。
- 如果过滤该 Intent 的 Activity 与 AAR 不匹配,或者有多个 Activity 可以处理该 Intent,再或者没有 Activity 可以处理该 Intent,则启动由 AAR 指定的应用。
- 如果 AAR 指定的应用都没法启动,则转到 Google Play,请用户根据 AAR 下载相应的应用。
注意:您可以使用前台调度系统替换 AAR 和 Intent 调度系统,以便在发现 NFC 标签后优先启动前台 Activity。使用此方法时,Activity 必须在前台运行才能替换 AAR 和 Intent 调度系统。
如果您仍希望过滤扫描到的不包含 AAR 的标签,则可以照常声明 Intent 过滤器。如果您的应用对其他不包含 AAR 的标签感兴趣,这将非常有用。例如,您可能需要保证您的应用能够处理由您部署的专有标签以及由第三方部署的常规标签。请注意,AAR 特定于搭载 Android 4.0 或更高版本的设备,因此,在部署标签时,您很可能需要将 AAR 和 MIME 类型/URI 结合使用,以支持各种设备。此外,在部署 NFC 标签时,请考虑:要如何编写 NFC 标签,才能使其支持大多数设备(Android 设备和其他设备)。为此,您可以定义相对唯一的 MIME 类型或 URI,从而使应用更容易区分它们。
Android 提供了 createApplicationRecord() 这个简单的 API 来创建 AAR。您只需将 AAR 嵌入 NdefMessage 中的任意位置即可。您不需要使用 NdefMessage 的第一条记录,除非 AAR 是 NdefMessage 中唯一的记录。这是因为 Android 系统会检查 NdefMessage 的第一条记录,以此来确定标签的 MIME 类型或 URI;在创建应用要过滤的 Intent 时需要用到标签的 MIME 类型或 URI。以下代码展示了如何创建 AAR:
NdefMessage msg = new NdefMessage(
new NdefRecord[] {
...,
NdefRecord.createApplicationRecord("com.example.android.beam")}
);
)
向其他设备传输 NDEF 消息
Android Beam 可在两台 Android 设备之间进行简单的点对点数据交换。需要将数据传输到另一台设备的应用必须在前台运行,并且要接收数据的设备不得处于锁定状态。当传输设备与接收设备的距离足够近时,传输设备会显示“触摸即可传输”界面。然后,用户可以选择是否将消息传输到接收设备。
注意:API 级别 10 中提供前台 NDEF 推送,其功能与 Android Beam 类似。此后,这些 API 已弃用,但可用于支持旧设备。如需了解详情,请参阅 enableForegroundNdefPush()
。
调用以下两种方法之一可为您的应用启用 Android Beam:
- setNdefPushMessage():接受 NdefMessage 以将其设置为待传输的消息。在两台设备的距离足够接近时自动传输消息。
- setNdefPushMessageCallback():接受包含 createNdefMessage()(在设备处于可接收数据的范围内时调用)的回调。该回调支持您根据需要创建 NDEF 消息。
Activity 一次只能推送一个 NDEF 消息,因此,如果设置了两个 NDEF 消息,setNdefPushMessageCallback() 将优先于 setNdefPushMessage()。要使用 Android Beam,必须满足以下一般准则:
- 传输数据的 Activity 必须在前台运行。两台设备的屏幕都必须处于解锁状态。
- 必须将要传输的数据封装到 NdefMessage 对象中。
- 接收传输数据的 NFC 设备必须支持 com.android.npp NDEF 推送协议或 NFC Forum 的 SNEP(简单 NDEF 交换协议)。API 级别 9 (Android 2.3) 到 API 级别 13 (Android 3.2) 的设备都需要使用 com.android.npp 协议。API 级别 14 (Android 4.0) 及更高版本的设备需要使用 com.android.npp 和 SNEP。
注意:如果您的 Activity 支持 Android Beam 且在前台运行,则标准 Intent 调度系统将停用。不过,如果您的 Activity 也支持前台调度,那么它仍然可以扫描与前台调度中设置的 Intent 过滤器相匹配的标签。
要启用 Android Beam,请执行以下操作:
- 创建一个 NdefMessage,其中包含要推送到其他设备的 NdefRecord。
- 调用带有 NdefMessage 的 setNdefPushMessage(),或者,调用 setNdefPushMessageCallback,将 NfcAdapter.CreateNdefMessageCallback 对象传入 Activity 的 onCreate() 方法中。这些方法至少需要您通过 Android Beam 启用一个 Activity,同时激活一个由其他 Activity 组成的可选列表。通常,如果两台设备处于通信范围内,而您的 Activity 只需要一直推送同一 NDEF 消息,您一般可以使用 setNdefPushMessage()。如果您的应用关注应用的当前上下文,并需要根据用户当前在您的应用中执行的操作来推送 NDEF 消息,则可以使用 setNdefPushMessageCallback。
以下示例展示了一个简单 Activity 如何调用 Activity 的 onCreate() 方法中的 NfcAdapter.CreateNdefMessageCallback。此示例还提供了一些方法来帮助您创建 MIME 记录:
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 nfcAdapter;
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
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
// Register callback
nfcAdapter.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[] { createMime(
"application/vnd.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()));
}
}
注意,此代码为 AAR 添加了注释,您可以将其移除。如果启用 AAR,则 AAR 中指定的应用始终会收到 Android Beam 消息。如果该应用不存在,则会启动 Google Play,请用户下载该应用。因此,对于搭载 Android 4.0 及更高版本的设备(如果使用了 AAR)而言,以下 Intent 过滤器在技术上是不需要的:
凭借此 Intent 过滤器,com.example.android.beam
应用现在可以在以下情况下启动:扫描到 NFC 标签或通过 Android Beam 接收到类型为 的 AAR,或者在 NDEF 格式的消息包含类型为 application/vnd.com.example.android.beam
的 MIME 记录时。
即使 AAR 能够保证启动或下载应用,但我们仍建议您使用 Intent 过滤器,因为它们允许您在应用中启动所选的 Activity,而不是始终启动由 AAR 指定的软件包内的主 Activity。AAR 不具备 Activity 级别的粒度。此外,由于某些 Android 设备不支持 AAR,因此您还应在 NDEF 消息的第一条 NDEF 记录中嵌入标识信息,以便在需要时进行过滤。
4、NFC与其他技术的比较
目前的近距离无线通信技术包括了RFID、蓝牙、红外等, NFC是一种短距离的高频无线通讯技术,电子设备之间允许进行非接触式点对点数据传输。其工作频率为 13.56MHz,通信距离 0~20cm(实际大部分产品都在 10cm 以内),传输速率可为106kbit/s、212kbit/s、424 kbit/s和848kbit/s。近距无线通信技术除NFC外,主要还包括射频识别(RFID)、蓝牙(Bluetooth)、紫蜂(ZigBee)、红外、 Wi-Fi等技术。以上各项技术都有各自的特点和优点,下图给出了 NFC 以及其他六种几种短距离无线通信技术在所列频段上性能的比较。
可以看出,NFC 技术具有极高的安全性,在短距离通信中具有性能优势,更重要的是成本较低,因此自其 2003 年问世以来,得到众多企业的关注和支持。
NFC与RFID的比较
第一,工作模式不同。NFC是将点对点通信功能,读写器功能和非接触卡功能集成进一颗芯片,而RFID则有阅读器和标签两部分组成。NFC技术既可以读取也可以写入,而RFID只能实现信息的读取以及判定。 [2]
第二,传输距离不同。NFC传输距离比RFID小的多,NFC 的传输距离只有10厘米,RFID的传输距离可以达到几米、甚至几十米。NFC是一种近距离的私密通信方式,相对于RFID来说NFC具有距离近、带宽高、能耗低、安全性高等特点。 [2]
第三,应用领域不同。NFC更多的应用于消费类电子设领域,在门禁、公交、手机支付等领域发挥着巨大的作用;RFID则更擅长于长距离识别,更多的被应用在生产、物流、跟踪、资产管理上。 [2]
近场通信NFC与蓝牙的比较
NFC和蓝牙都是短程通信技术,相对于蓝牙很早就被集成到移动电话中并已经被普及,NFC最近几年才开始被集成进移动电话中,并且到目前为止只集成在少数移动电话中。 [2]
第一,建立时间不同,NFC通信设置程序简单,通信建立时间很短,仅需0.1s左右;而蓝牙通信设置程序相对复杂,通信建立时间较长,大概需要6s。 [2]
第二,传输距离不同,NFC传输距离只有10cm,而蓝牙传输距离可达10m。但NFC在传输功耗和安全性方面略优于蓝牙。 [2]
第三,传输速度和工作频率不同,NFC工作频率为13.56MHz, 传输速度最大424 Kbit/s,而蓝牙工作频率为2.4GHz,传输速度可 达2.1 Mbit/s。 [2]
近场通信NFC与红外的比较
NFC和红外传输相比,传输距离相当,但比红外传输速度更快,NFC传输速度最大可达424 Kbit/s,而红外传输速度大概 100Kbit/s。建立时间NFC比红外略快,NFC建立时间为0.1s, 红外传输建立时间为0.5s。红外传输必须严格的对齐才能传输数据,且中间不能有障碍物,而NFC则没有这种限制;另外NFC比红外更安全可靠。