草庐IT

Android系统编程入门系列之硬件交互——通信硬件NFC

星城之路 2023-03-28 原文

上篇文章介绍了接入式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:schemeandroid:hostandroid: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对象之后,可以作为参数传入NdefMessageNFC消息类的构造方法中,从而创建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]得到TAGNFC标签类的对象。

另外可以通过其getTechList()方法,获取通过意图行为android.nfc.action.TECH_DISCOVERED启动的NFC硬件中所使用技术列表。其中系统支持的技术类型均实现了android.nfc.tech.TagTechnology标签技术接口。

在得到的TagNFC标签类的对象后,可以遵循相关技术类型对标签进行读写操作。对实现了TagTechnology接口的具体技术类中,可以调用静态方法get(Tag tag)得到具体的技术类对象,其参数即得到的TagNFC标签类对象。在实现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的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  4. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  9. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  10. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

随机推荐