Android开发----NFC标签读写
前言
最近因为项目需要,特意学习了NFC的Android开发。加上之前并没有系统地学习过Android开发知识,起手比较困难,搞了半天才算一知半解。怎么办呢?不知道大家在平时学习,尤其是需要撰写论文或者报告的时候,有没有过这个感受。我们一开始收集和整理资料,往往是“雾里看花”,被一些“高级”的专业术语、概念铺陈搞得头晕脑胀。而一些仅有的博文也都是转来转去,其质量也良莠不齐,很多都解释得云里雾里。可是,在真正落笔撰文之时,很多之前不解的概念却渐渐清晰起来。究其原因,是因为文字需要逻辑性,而将知识转化为文字强迫我们在心中对已有的原材料进行梳理和归纳,同时还需要进行探索性地实践得出预期结论。一旦步入正轨,便可按图索骥。以前做调研,习惯于将搜索得到的文章用印象笔记剪辑保存(免费广告,强力推荐),却从未将自己的理解书以文字,虽然当时理解,由于理解不深,过段时间便忘。为了改变这种状况,还是向学霸大神们学习,做到笔耕不辍。一是建立自己的知识库体系,促进消化吸收;二是跟众多和我一样在成长路上的朋友们分享交流学习的心得,举一反三。
下面开始正题:
阅读之前
你需要有一点Android的开发基础知识,不要连AndroidManifest.xml文件干什么用的都不知道,那样的话看起来会很吃力哦。
NFC简介
NFC技术由非接触式射频识别(RFID)演变而来,由飞利浦半导体(现恩智浦半导体公司)、诺基亚和索尼共同研制开发,其基础是RFID及互连技术。近场通信(Near Field Communication,NFC)是一种短距高频的无线电技术,在单一芯片上结合感应式读卡器、感应式卡片和点对点的功能,能在13.56MHz频率运行于4厘米距离内,与兼容设备进行识别和数据交换。其传输速度有106 Kbit/秒、212 Kbit/秒或者424 Kbit/秒三种。目前近场通信已通过成为ISO/IEC IS 18092国际标准、ECMA-340标准与ETSI TS 102 190标准。现今这项技术在日韩被广泛应用。手机用户凭着配置了支付功能的手机就可以行遍全国:他们的手机可以用作机场登机验证、大厦的门禁钥匙、交通一卡通、信用卡、支付卡等等。
NFC标签的复杂度不一。简单的标签仅能够提供读写语义,有时编程域是一次性的,写完卡片就变成只读。更复杂一点的tag能够提供数学运算,拥有加密硬件保护区块的访问。最最复杂的tag包含操作环境,允许tag上执行的代码进行交互。我们还能够以各种格式来向tag中写入存储数据,但很多Android的API框架都是基于NFC论坛制定的NDEF标准。
广告时间,下图是我司的NFC标签产品,可以贴在任意表面平整的物体上。
目前众多手机厂商均有自带NFC内置芯片的手机型号,如小米3,三星的GalaxyNote 3,Nexus5,微软的Lumia 1020等等。苹果公司新推产品iPhone 6、iPhone 6 Plus甚至Apple Watch中均配备NFC芯片,可惜这几款产品的NFC功能被锁定,只能在移动支付Apple Pay中得到应用。但管中窥豹,可见一斑,NFC能够为人们的生活带来诸多便捷,将成为未来智能手机的必备配置。
NDEF
必须要先着重讲一下NDEF,因为NFC开发过程中基本上就是和该数据类型打交道。信息的传输总是离不开各种各样的协议,如用于Internet通信的HTTP协议、TCP/IP协议,蓝牙通信协议,WIFI的IEEE 802.11协议等等。协议中往往规定了通信的状态转换、时序以及数据交换格式。NFC的数据交换格式NFC Data Exchange Format(NDEF)是NFC组织约定的NFC tag中的数据格式。NDEF是轻量级的紧凑的二进制格式,可带有URL、vCard和NFC定义的各种数据类型。NDEF信息(NdefMessage)由各种数据记录(NdefRecord)组成,而各个记录由报头(Header)和有效载荷(Payload)组成,其中NDEF记录的数据类型和大小由记录载荷的报头注明,这里的报头包含3部分,分别为标识符(Identifier),数据长度(Length)和类型符(Type)。
关于NDEF规范的官方文档,可以到 万能的百度文库进行下载。(官方网站居然收费100美元,简直无情)
NFC开发(以下大部分翻译自android开发官网说明)
根据手机设备所扮演的具体角色不同,NFC操作主要有三种模式。
读/写器模式
NFC设备充当读写器,对被动式NFC标签进行读或者写。
P2P模式
NFC设备与其他NFC设备进行数据交换。例如使用NFC来分享图片、名片、音乐等。
仿真卡模式
NFC设备充当NFC卡,外部读卡器能够访问内部数据。例如可以充当公交卡、银行卡。
本文着重讲第一种模式。
开发平台
Eclipse + ADT + Android SDK + Galaxy Nexus
介绍Android开发平台如何搭建的博客有很多,这里就不再赘述了。
苹果是明确表示近期不会开放NFC的API给开发者了,而微软的WP系统我(yong)不(de)太(ren)了(tai)解(shao)。感谢Google,目前我们唯一能够玩玩的也就只有Android系统的NFC开发了。本文选用的测试机为三星的Galaxy Nexus,算是Google的亲儿子哈哈。
Tag分发系统
NDEF的读操作是通过Tag分发系统处理的,该系统分析被发现的NFC标签,对数据进行大致分类,然后启动某个对该数据感兴趣的APP。想要处理被扫描NFC标签的APP能通过声明一个intent过滤器来请求处理数据。
在显示屏被解锁时,Android设备总是在尝试寻找NFC标签,除非在设置中禁用NFC。当Android设备发现一个Tag标签,我们希望能够有由最合适的Activity去处理该intent,而不需要询问用户该用哪个APP。因为在扫描NFC标签时,手机往往与标签离得很近,如果需要用户决定用何种App,很有可能会迫使他们将设备从标签上拿开,从而会中断连接。好的做法是你所涉及的Activity应当只处理感兴趣的NFC标签,从而防止Activity选择界面出现。
为了达到该目的,你可以这样做:
1. 解析NFC标签并得到MIME类型或者标识tag中数据载荷的URI。
2. 将MIME类型或者URI和有效载荷封装进intent。
3. 启动一个基于该intent的activity。
NFC标签映射到MIME类型和URI
在你开始着手写NFCAPP时,一件重要的事就是要搞清楚NFC标签的不同类型,tag分发系统如何解析NFC标签,以及tag分发系统在检测到NDEF信息后所做的特殊操作。NFC标签涵盖很多技术,数据写入的方式也大相径庭。Android能够完美地支持NFC论坛制定的NDEF标准,所以请放心大胆地使用NDEF。
我们之前也介绍了NDEF的相关知识,下面将详细介绍Android如何处理NDEF格式的标签的。当Android设备扫描到包含有NDEF格式数据的标签时,它会先尝试解析该信息并找出数据的MIME类型或者URI标识。系统会先读取NdefMessage中的第一个NdefRecord,从而决定改如何解释整个NdefMessage。在一个风格良好的NdefMessage中,第一个NdefRecord包含如下4个域。
3-bitTNF(Type Name Format)
指明该如何解释variablelength type域,合法值见Table 1.
Variablelength type
描述记录的类型。如果使用TNF_WELL_KNOWN,则用该域来描述RecordType Definition(RTD)。合法的RTD值见Table 2.
Variablelength ID
record的UID。这个域不常用,但是如果你需要一个区分record的标记,就建一个ID给它。
Variablelength payload
读写的真实数据。不要以为第一个NdefRecord中就包含了所有你要的数据,还要把NdefMessage之后的NdefRecord考虑在内。
Table1. Supported TNFs and their mappings
Type Name Format (TNF) |
Mapping |
URI based on the type field. |
|
Falls back to ACTION_TECH_DISCOVERED. |
|
URI based on the URN in the type field. The URN is encoded into the NDEF type field in a shortened form:<domain_name>:<service_name>. Android maps this to a URI in the form: |
|
MIME type based on the type field. |
|
Invalid in the first record, so falls back toACTION_TECH_DISCOVERED. |
|
Falls back to ACTION_TECH_DISCOVERED. |
|
MIME type or URI depending on the Record Type Definition (RTD), which you set in the type field. See Table 2. for more information on available RTDs and their mappings. |
Table2. Supported RTDs for TNF_WELL_KNOWN and theirmappings
Record Type Definition (RTD) |
Mapping |
Falls back to ACTION_TECH_DISCOVERED. |
|
Falls back to ACTION_TECH_DISCOVERED. |
|
Falls back to ACTION_TECH_DISCOVERED. |
|
Falls back to ACTION_TECH_DISCOVERED. |
|
URI based on parsing the payload. |
|
MIME type of |
|
URI based on payload. |
tag分发系统尝试使用TNF和type域将某种MIME类型或者URI映射到NDEF信息。如果成功的话,它将带有实际载荷的信息封装在一个ACTION_NDEF_DICOVERED的intent中。但是,有时tag分发系统也会出现无法通过第一条NdefRecord来识别数据类型的情况:当NDEF数据无法被映射为某个MIME或者URI,或者当NFC标签并不包含以NDEF开头的数据。在这些情况下,Tag对象会含有tag实现技术信息,并且载荷会被封装进ACTION_TECH_DISCOVERED的intent中。
NFC标签分发到APP
当tag分发系统完成NFC标签信息封装并生成一个intent后,将该intent发送给那些经过过滤后能够接受该intent的APP。如果有多于一个APP能够处理该intent,那么用户也就必须通过Activity选择器来选择所需的Activity。tag分发系统定义了三种intent,根据优先级从高至低的次序罗列如下:
1. ACTION_NDEF_DISCOVERED
当扫描到的tag中包含有NDEF载荷且为已知类型,该intent将用来启动Activity。该intent的优先级最高,tag分发系统总是先于其他intent用该intent来启动Activity。
2. ACTION_TECH_DISCOVERED
如果manifest中没有注册处理ACTION_NDEF_DISCOVERED类型的intent,该intent将被用以启动Activity。如果tag中没有包含可以映射到MIME或者URI类型的数据,或者虽然没有包含NDEF数据,但是已知的tag技术,则该intent也会被直接启用。
3. ACTION_TAG_DISCOVERED
如果以上两个intent都没人疼,那么该intent就会启动。
下图是分发流程
AndroidManifest.xml
索取NFC权限
Ÿ 为了能够使用Android手机的NFC功能,需要在Manifest文件中添加相应的权限:
<uses-permission android:name="android.permission.NFC"/>
Ÿ 指定Android SDK的最小版本。自API 10之后,NFC的功能更加完善,因此这里我们将最小版本要求定位10.
<uses-sdk android:m