Android系统编程入门系列之硬件交互——通信硬件NFC
在上篇文章介绍了接入式USB硬件的简单使用,接下来将介绍不依赖物理连接的硬件通信了。本文的重点是近距离通信的硬件NFC。
NFC硬件
应用程序中可以通过NFC硬件读取或发送指定协议的技术实现,在Android10.0之前甚至可以封装大段的NDEF数据。另外,Android系统基于NFC的特性,结合移动设备的安全元件,构建了一层HCE架构,从而应用于安全级别较高的公交卡刷卡或付款交易等操作。
权限声明
要想使用NFC硬件的相关功能,必须要声明权限,在应用程序的清单文件中声明<uses-permission />
标签,其中的android:name
属性值为android.permission.NFC
。
当然,为了强调应用程序需要运行在支持NFC硬件的设备上,也可以在应用程序的清单文件中声明<uses-feature />
标签,其中的android:name
属性值为android.hardware.nfc
。
使用流程
由于NFC硬件是在近距离接触后即可触发,所以首先要在应用程序中确定触发NFC连接后要响应的界面Activity
。在清单文件注册的<activity></activity>
标签内部,增加意图过滤<intent-filter></intent-filter>
标签,并在该标签内部添加<action />
标签,并指定android:name
属性值分别为android.nfc.action.NDEF_DISCOVERED
作为NDEF数据传输行为、android.nfc.action.TECH_DISCOVERED
作为技术标签行为或android.nfc.action.TAG_DISCOVERED
作为普通行为。
上边指定的意图行为有三种方式,但是在连接NFC硬件后,系统将按照上述顺序优先启动对应的界面Activity
。另外针对上述三种不同的意图行为,还要在清单文件下分别追加相应的配置。
在通过上述三种方式收到Intent
意图启动的界面Activity
中,可以通过getIntent()
获取启动传入的Intent
意图对象。在该对象中,可以接收其他NFC硬件输入的标签及相关内容。
默认功能
针对action
值为android.nfc.action.TAG_DISCOVERED
的配置,由于是优先级最低的意图行为,因此在上面两种意图行为及配置未调起时,就会调用该意图行为绑定的界面Activity
。因此该意图行为下不需要其他的配置参数。
在启动的界面Activity
中,调用Intent
对象的getParcelableExtra(String name)
方法,传入参数 name 值为NfcAdapter.EXTRA_TAG="android.nfc.extra.TAG"
,得到android.nfc.TagNFC标签类型的对象,该对象中记录了标签的基本信息。
NDEF数据传输功能
针对action
值为android.nfc.action.NDEF_DISCOVERED
的配置,还要声明要传输的数据类型。同样在意图过滤的<intent-filter></intent-filter>
标签内部,添加<data />
标签。可支持传输的数据类型可以使用的表示方式,包括 MIME TYPE 类型的结构,和 URI 结构,二选一皆可。在<data />
标签中使用android:mimeType
属性,可以设置 MIME TYPE 结构的数据类型,通常如属性值为text/plain
的文本类型。另外,在<data />
标签中使用android:scheme
、android:host
、android:pathPrefix
三个属性同时标注URI内容。
在启动的界面Activity
中,调用Intent
对象的getParcelableArrayExtra(String name)
方法,传入参数 name 值为NfcAdapter.EXTRA_NDEF_MESSAGES="android.nfc.extra.NDEF_MESSAGES"
,得到Parcelable[]
数组可以分别强转为android.nfc.NdefMessage用以保存消息内容的类型对象数组。当使用android.nfc.action.NDEF_DISCOVERED
意图行为过滤的NFC硬件启动后,可通过该方法获取NDEF消息内容。
在应用程序内可以自定义NDEF消息体内容并发送。借助android.nfc.NdefRecordNFC记录类。在该类中有多个静态方法,包括createExternal(String domain, String type, byte[] data)
创建有携带数据的NFC记录对象;createMime(String mimeType, byte[] mimeData)
创建MIME类型的NFC记录对象;createTextRecord(String languageCode, String text)
创建短文本内容的NFC记录对象;createUri (Uri uri)
创建Uri
类型的NFC记录对象等。
在创建NdefRecord
对象之后,可以作为参数传入NdefMessage
NFC消息类的构造方法中,从而创建NdefMessage
对象,将该对象作为参数,传入NdefAdapter
对象的setNdefPushMessage(NdefMessage message, Activity activity, Activity... activities)
方法中,这样在当前参数 activity 中将会一直发送参数 message 中的内容。
从Android10.0即API级别29开始,NFC功能的NDEF消息传输功能就被废弃了,因此其相关功能方法在以后的版本中也将不再支持。
标签技术功能
针对action
值为android.nfc.action.TECH_DISCOVERED
的配置,还要通过资源文件声明要依赖的技术集。资源文件的声明是在注册的<activity></activity>
标签内部,添加<meta-data />
标签,同样设置其属性android:name
值为android.nfc.action.TECH_DISCOVERED
,更别忘了设置属性android:resource
,其值为保存在 res/xml 目录下的资源文件。而资源文件的定义,是在 res/xml 路径下,定义 xml 格式的资源文件,在该文件中使用<tech-list></tech-list>
标签作为最外层的集合,在该标签中包含了一堆使用<tech>
标签定义的可支持技术。这些技术的定义均实现了android.nfc.tech.TagTechnology标签技术接口,在各种实现类中定义了相应技术的常量值。
在启动的界面Activity
中,同样可以调用Intent
对象的getParcelableExtra(String name)
方法,传入参数 name 值为[NfcAdapter.EXTRA_TAG]得到TAG
NFC标签类的对象。
另外可以通过其getTechList()
方法,获取通过意图行为android.nfc.action.TECH_DISCOVERED
启动的NFC硬件中所使用技术列表。其中系统支持的技术类型均实现了android.nfc.tech.TagTechnology标签技术接口。
在得到的Tag
NFC标签类的对象后,可以遵循相关技术类型对标签进行读写操作。对实现了TagTechnology
接口的具体技术类中,可以调用静态方法get(Tag tag)
得到具体的技术类对象,其参数即得到的Tag
NFC标签类对象。在实现TagTechnology
接口的对象中,需要首先调用connect()
建立连接;之后可以根据不同的技术实现,调用相关的读写操作方法;最终在操作结束后,调用close()
断开连接即可。
HCE服务功能
该功能是由Android系统实现的一套在后台使用NFC进行交易等服务的架构。该架构主要依赖android.nfc.cardemulation.HostApduService抽象服务类。在自定义的服务中必须继承自HostApduService
服务类,并实现其两个抽象方法,接收并响应数据的byte[] processCommandApdu(byte[] apdu, Bundle extras)
方法,和NFC切换或关闭当前APDU连接时的void onDeactivated(int reason)
方法。
在定义了继承自HostApduService
的服务之后,需要在清单文件中注册该服务组件,在<service></service>
标签中要设置android:exported
属性值为true
。同时在标签内嵌入<intent-filter></intent-filter>
意图过滤标签中,设置行为值为HostApduService.SERVICE_INTERFACE="android.nfc.cardemulation.action.HOST_APDU_SERVICE"
。另外要在标签内嵌入<meta-data />
额外数据标签,设置其android:name
属性值为HostApduService.SERVICE_META_DATA="android.nfc.cardemulation.host_apdu_service"
,设置其android:resource
属性为包含 AID 群组的资源文件。
定义的 AID 群组,是由NFC卡提供的应用唯一标识,如用于支付的银联储蓄卡、公交卡等,每张卡都有唯一的16字节组成的AID。而在资源文件中可以定义该应用程序自定义的HostApduService
服务中允许交易的 AID 群组,该群组的所有 AID 只要有一个 AID 连接当前设备的 NFC 硬件,都会唤起 HCE 服务。
在应用程序的资源文件 res/xml 目录下,可以创建自定义的资源文件以定义上述 AID 群组,在资源文件中根标签为<host-apdu-service></host-apdu-service>
,在其中可以嵌入多组标签<aid-group></aid-group>
用来标记 AID 群组,其中设置android:description
属性值为字符串类型的群组介绍,还需要设置android:category
属性值为android.nfc.cardemulation.CardEmulation.CATEGORY_PAYMENT="payment"
作为支付使用、或者属性值为android.nfc.cardemulation.CardEmulation.CATEGORY_OTHER="other"
。在该标签内部,就可以嵌入多组<aid-filter / >
标签并设置其android:name
属性值,用以标记当前群组下的 AID 值。
Android系统编程入门系列之硬件交互——通信硬件NFC的更多相关文章
- Android系统编程入门系列之加载界面Activity
上回说到应用初始化加载及其生命周期,在Android系统调用Applicaiton.onCreate()之后,继续创建并加载清单文件中注册的首个界面即主Activity,也可称之为入口界面.主Acti ...
- Android系统编程入门系列之硬件交互——多媒体摄像头
多媒体系列硬件 多媒体包括图片.动画.音频.视频,这些多媒体素材的采集(输入)主要依靠摄像头和麦克风等硬件设备转化为基础数据,而他们的播放渲染(输出),则需要依靠具有相关功能的编解码软件.当然随着硬件 ...
- Android系统编程入门系列之硬件交互——传感器
到目前为止,关于应用程序与用户之间的相关内容便比较肤浅的大致介绍完毕.而在整个系统架构中,应用程序与用户之间的交互,犹如参天大树上的枝干和树叶,交互起来五彩缤纷,但使整个生态系统保持生命力的核心,在于 ...
- Android系统编程入门系列之硬件交互——通信硬件USB
在硬件交互的首篇对设备硬件的分类中,互联通信系列硬件主要用来与其他设备进行数据交互.从本文开始,将重点介绍该系列相关硬件. 互联通信系列硬件 根据硬件的可通信距离,由近及远分为USB.NFC.蓝牙.W ...
- Android系统编程入门系列之硬件交互——通信硬件Bluetooth
通信硬件NFC的文章,虽然可以在Android系统中通过非直接接触的形式与支持NFC硬件的设备通信,但是也只能交互一些简短的标签内容,对大量的持续性数据,却并不能很好的支持.因此针对这个弊端,可以考虑 ...
- Android系统编程入门系列之硬件交互——多媒体展示
前两篇文章通过麦克风硬件和摄像头硬件分别采集音频和视频的多媒体数据,在得到的多媒体数据通常是以编码文件的格式存储,在用户需要展示时,可通过设备的内置扩音器或蓝牙耳机等硬件播放音频,通过设备的显示屏或外 ...
- Android系统编程入门系列之硬件交互——无线通信WLAN
Android系统的移动设备大多支持无线WLAN技术.利用该技术,不仅能实现互联网通信,还能实现无线定位,热点共享等远程通信功能.针对使用WLAN的不同功能,可能需要分别申请不同的权限声明,同时调用不 ...
- Android系统编程入门系列之硬件交互——通信硬件电信SIM卡
现在的SIM卡通常具备基站定位.语音通话.短信消息.网络流量这四大功能,而在移动端是无法对SIM卡使用基站定位功能的,所以这里只介绍移动端如何使用SIM卡实现语音通话.短信消息.数据流量三个功能. 语 ...
- Android系统编程入门系列之界面Activity交互响应
在上篇文章中已经了解到界面Activity的绘制完全依赖其加载的视图组件View,不仅如此,用户的每次触摸操作都可以在界面Activity内接收并响应,也可以直接传递给其中的某个视图View响应.本文 ...
随机推荐
- response.setHeader("xxx","大侠")如果赋值中文,那么将不会在页面出值,
response.setHeader("xxx","大侠")如果赋值中文,那么将不会在页面出值,而非中文就可以在页面出值
- [C# Expression] 之动态创建表达式
上一篇中说到了 Expression 的一些概念性东西,其实也是为了这一篇做知识准备.为了实现 EFCore 的多条件.连表查询,简化查询代码编写,也就有了这篇文章. 在一些管理后台中,对数据进行 ...
- IDEA 无法显示 Run Dashboard 的解决方法
前言 最近开始接触微服务的项目,项目很多有时候本地调测需要启动多个项目,看到同事都是使用dashboard管理项目,服务和端口排列的整整齐齐.但是我dashboard里面啥都没有,一顿百度最后解决问题 ...
- 【LeetCode】1413. 逐步求和得到正数的最小值 Minimum Value to Get Positive Step by Step Sum
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 求和 日期 题目地址:https://leetcode ...
- 【九度OJ】题目1080:进制转换 解题报告
[九度OJ]题目1080:进制转换 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1080 题目描述: 将M进制的数X转换为 ...
- 【LeetCode】376. Wiggle Subsequence 解题报告(Python)
[LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...
- Towards Evaluating the Robustness of Neural Networks
目录 概 主要内容 基本的概念 目标函数 如何选择c 如何应对Box约束 attack attack attack Nicholas Carlini, David Wagner, Towards Ev ...
- Mysql溯源-任意文件读取👻
Mysql溯源-任意文件读取 前言 读了<MySQL蜜罐获取攻击者微信ID>的文章,文中说明了通过mysql蜜罐读取攻击者微信ID的过程,抱着学习的态度尝试了一下 原理 mysql中有一个 ...
- oracle中connect by prior的使用
作用 connect by主要用于父子,祖孙,上下级等层级关系的查询 语法 { CONNECT BY [ NOCYCLE ] condition [AND condition]... [ START ...
- 使用 DDL 语句分别创建仓库表、供应商表、产品表和入库表,并对其进行操作
查看本章节 查看作业目录 需求说明: 使用 DDL 语句分别创建仓库表.供应商表.产品表和入库表 使用 DML 语句分别新增一条仓库表.供应商表.产品表和入库表记录 使用 DML 语句更新满足指定条件 ...