本文基本是结合Android Developer
官网进行梳理,NFC
系列将由基本概念到具体操做,到NDEF
和非NDEF
的数据读写。html
参考资料android
NFC概览编程
近距离无线通讯 (NFC :``Near Field Communication``)
是一组近距离无线技术,一般只有在距离不超过 4
厘米时才能启动链接。借助 NFC
,您能够在 NFC
标签与 Android
设备之间或者两台 Android
设备之间共享小型负载。浏览器
标签的复杂度可能各有不一样markdown
简单标签仅提供读取和写入语义,有时可以使用一次性可编程区域将卡片设置为只读网络
较复杂的标签可提供数学运算,还可以使用加密硬件来验证对扇区的访问权限app
最为复杂的标签可包含操做环境,容许与针对标签执行的代码进行复杂的互动框架
存储在标签中的数据也能够采用多种格式编写,但许多 Android
框架 API
都基于名为 NDEF
(NFC
数据交换格式)的 NFC Forum 标准。ide
支持 NFC
的 Android
设备同时支持如下三种主要操做模式:oop
读取器/写入器模式:支持 NFC
设备读取和/或写入被动 NFC
标签和贴纸。
点对点模式:支持 NFC
设备与其余 NFC
对等设备交换数据;Android Beam
使用的就是此操做模式。
卡模拟模式:支持 NFC
设备自己充当 NFC
卡。而后,能够经过外部 NFC
读取器(例如 NFC
销售终端)访问模拟 NFC
卡。
主要有两种 ---- 无源NFC设备与有源NFC设备
无源NFC
设备包括NFC
标签和其余小型发射器,它们能够向其余NFC
设备发送信息,而不须要电源。可是,它们不能处理来自其余源的信息,也不能链接到其余无源设备。
有源NFC
设备可以发送和接收数据,而且能够彼此通讯,也能够与无源设备通讯。目前来讲,智能手机是最多见的有源NFC
设备,其它常见的例子还包括公交读卡器和支付终端。
若是从工做模式上来介绍的话,能够这样归纳
NFC
工做模式分为被动模式和主动模式。
被动模式中NFC
发起设备(也称为主设备)须要供电设备,主设备利用供电设备的能量来提供射频场,并将数据发送到NFC目标设备(也称做从设备),传输速率需在106kbps
、212kbps
或424kbps
中选择其中一种。从设备不产生射频场,因此能够不须要供电设备,而是利用主设备产生的射频场转换为电能,为从设备的电路供电,接收主设备发送的数据,而且利用负载调制(load modulation
)技术,以相同的速度将从设备数据传回主设备。由于此工做模式下从设备不产生射频场,而是被动接收主设备产生的射频场,因此被称做被动模式,在此模式下,NFC
主设备能够检测非接触式卡或NFC
目标设备,与之创建链接。
主动模式中,发起设备和目标设备在向对方发送数据时,都必须主动产生射频场,因此称为主动模式,它们都须要供电设备来提供产生射频场的能量。这种通讯模式是对等网络通讯的标准模式,能够得到很是快速的链接速率。
它的工做原理是什么呢?就像蓝牙、Wi-Fi
以及其余各类无线通讯技术同样,NFC
的工做原理也是经过无线电波发送信息,也是无线数据传输的一种标准。这意味着设备必须遵照特定的规范,才能正确地相互通讯。在NFC中使用的技术是基于旧的免接触式射频识别(RFID
)演变而来,即使用电磁感应来传输信息,并向下兼容RFID
。
这也是NFC
和蓝牙/WiFi的一个主要区别,NFC
使用电磁感应原理,有源NFC元件能够在无源元件中感应出电流和发送数据。这意味着无源设备不须要本身的电源,当NFC组件进入通讯范围时,它们能够由有源NFC
组件产生的电磁场提供动力。不过,NFC
技术没有足够的感应力来给咱们的智能手机充电,QI
无线充电也是基于一样的原理。
NFC
的工做频率为13.56MHz,距离在10厘米内,其传输速度有106Kbit/秒、212Kbit/秒或者424Kbit/秒三种,这种传输速度对于传输图片和音乐等文件已经足够了。
NFC
的优点
NFC
相比蓝牙的一大优点是功耗更少,这使得NFC
很是适合于做为无源设备,好比前面提到的广告标签,由于它们能够在没有电源的状况下运行。
还有一个主要优点:链接速度更快。NFC
因为使用了电感耦合技术,无需手动配对,在两个设备之间创建链接仅需不到十分之一秒的时间。虽然现代蓝牙链接速度已经很是快了,但依然远不及NFC
的链接速度,而快速的链接对于某些场景是相当重要的,例如移动支付。
固然,缺点也有
NFC
的传输距离比蓝牙短得多。上面说过,NFC
的最大传输范围约为10厘米,而蓝牙链接的传输距离能够高达10米甚至更远。NFC
的另外一个缺点是其传输速度比蓝牙慢不少。NFC
传输数据的最高速度仅为424 kbit/s,而蓝牙2.1的传输速度为2.1 Mbit/s,**蓝牙LE(低功耗)**的传输速度也达到了为1 Mbit/s。将 NDEF
数据与 Android
结合使用时,会有两个主要用例
从 NFC
标签读取 NDEF
数据
NFC
标签读取 NDEF
数据的操做由标签调度系统进行处理,该系统会分析已发现的 NFC
标签,对相应数据进行适当分类,而后启动对分类后的数据感兴趣的应用。若是某个应用想要处理扫描到的 NFC
标签,则能够声明 Intent 过滤器,并请求对数据进行处理使用 Android Beam™ 将 NDEF
消息从一台设备传输到另外一台设备
Android Beam™
功能,设备能够将 NDEF
消息推送到另外一台设备,方法是将两台设备靠在一块儿。与蓝牙等其余无线技术相比,这种互动可提供更简便的数据发送方式,由于使用 NFC
时无需手动发现设备并将其配对。当两台设备之间的距离近到必定范围内时,系统会自动开始链接。Android Beam
功能经过一组 NFC API
提供,所以任何应用均可以在设备间传输信息。例如,通信录、浏览器和 YouTube
应用可以使用 Android Beam
在多台设备之间共享联系人信息、网页和视频。Android
设备一般会在屏幕解锁后查找 NFC
标签,除非设备的“设置”菜单中停用了 NFC
功能。
在 Android
设备发现 NFC
标签后,指望的行为就是让最合适的 Activity
来处理该 Intent
,而不是询问用户应使用哪一个应用。
因为设备须要在很是近的范围内扫描 NFC 标签,所以,让用户手动选择 Activity
可能会迫使他们将设备从标签处移开并致使链接中断。应以适当方式开发 Activity
,使其仅处理所关注的 NFC
标签,以免 Activity
选择器出现。为了解决这个问题,Android
提供了一个特殊的标签调度系统,用于分析扫描到的 NFC
标签、解析它们并尝试找到对扫描到的数据感兴趣的应用。这个标签调度系统经过如下操做来实现这些目的:
解析 NFC
标签并肯定 MIME
类型或 URI
(后者用于标识标签中的数据负载)。
将 MIME
类型或 URI
与负载一块儿封装到 Intent
中。如何将 NFC 标签映射到 MIME 类型和 URI 中介绍了前两个步骤。
根据 Intent
启动 Activity
。如何将 NFC 标签分发到应用中介绍了此步骤。
Android
对 NFC Forum 定义的 NDEF
标准的支持最完备,NDEF
数据封装在包含一条或多条记录(NdefRecord
)的消息(NdefMessage
)中,也就是NdefMessage
消息中会有很多NdefRecord
记录,咱们都是先建立NdefRecord
记录后再放到NdefMessage
中。
注意:要下载完整的 NDEF
规范,请转到 NFC Forum 规范和应用文档网站,并参阅建立常见类型的 NDEF 记录,查看有关如何构造 NDEF 记录的示例。
当 Android
设备扫描包含 NDEF
格式数据的 NFC
标签时,它会解析该消息并尝试肯定数据的 MIME 类型或起标识做用的 URI
。为此,系统须要读取 NdefMessage
中的第一条 NdefRecord
,以肯定如何解读整个 NDEF
消息(一个 NDEF
消息可能具备多条 NDEF
记录)。在格式正确的 NDEF
消息中,第一条 NdefRecord
包含如下字段
3 位 TNF(类型名称格式)
表示如何解读可变长度类型字段。下表 中介绍了有效的值。
详细可查看 官网表1
可变长度类型
介绍了记录的类型。若是使用 TNF_WELL_KNOWN
,那么请使用此字段来指定记录类型定义 (RTD
)。下表 中介绍了有效的 RTD
值
详细可查看 官网表2
可变长度 ID
记录的惟一标识符。此字段并不常用,但若是您须要对标签进行惟一标识,则可为其建立 ID
可变长度负载
您要读取或写入的实际数据负载。一个 NDEF
消息能够包含多条 NDEF
记录,所以不要假定 NDEF
消息的第一条 NDEF 记录中就有完整的负载
具体操做,后续会进行代码分析,这里能够对照看下小米碰碰贴的NFC的NDEF记录
具体支持可查看 官网
Android
设备还能够选择支持如下标签技术
当标签调度系统建立完用于封装 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
可以使您在更恰当的时间启动应用,从而为用户带来更好的体验
用于访问 NFC
硬件的 NFC <uses-permission>
元素
<uses-permission android:name="android.permission.NFC" />
复制代码
API 级别 9
仅经过 ACTION_TAG_DISCOVERED
支持有限的标签调度,可是如今target API
都到30
了,因此这块基本不须要修改
<uses-feature android:name="android.hardware.nfc" android:required="true" />
复制代码
ACTION_NDEF_DISCOVERED
如下示例展现了如何过滤 MIME 类型为 text/plain
的 ACTION_NDEF_DISCOVERED
Intent
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
复制代码
如下示例展现了如何过滤采用 https://developer.android.com/index.html
形式的 URI
<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>
复制代码
ACTION_TECH_DISCOVERED
必须建立一个 XML
资源文件,用它在 tech-list
集内指定您的 Activity
所支持的技术。若是 tech-list
集是标签所支持的技术(可经过调用 getTechList()
来获取)的子集
如下示例定义了全部技术。您能够移除本身不须要的技术。将此文件(你能够随便命名)保存到 <project-root>/res/xml
文件夹中
<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>
复制代码
如下示例展现了如何与支持 NfcA
和 Ndef
技术的标签或者支持 NfcB
和 Ndef
技术的标签相匹配
<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>
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
复制代码
最后清单文件中添加
<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>
复制代码
ACTION_TAG_DISCOVERED
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
复制代码
若是某个 Activity
因为 NFC
Intent
而启动,您能够从该 Intent
中获取有关扫描到的 NFC
标签的信息。Intent
能够包含如下 extra
,具体取决于扫描到的标签
EXTRA_TAG
(必需):一个 Tag
对象,表示扫描到的标签
EXTRA_NDEF_MESSAGES
(可选):从标签中解析出的一组 NDEF
消息。此 extra
对于 ACTION_NDEF_DISCOVERED
Intent
而言是必需的
EXTRA_ID
(可选):标签的低级别 ID