硬件交互的首篇对设备硬件的分类中,互联通信系列硬件主要用来与其他设备进行数据交互。从本文开始,将重点介绍该系列相关硬件。

互联通信系列硬件

根据硬件的可通信距离,由近及远分为USB、NFC、蓝牙、WLAN,SIM卡槽,这些硬件之间的功能原理及关系可以查找其他资料详细学习。总之,他们为当前设备与其他设备的交互搭建了桥梁,只要双方设备均遵循该系列硬件的协议,就可以在硬件层互相通信,而设备上的Android操作系统便会将硬件层的数据转换为应用层数据,进而与应用程序交互。这样也就实现了两个不同设备上的应用程序间的交互方案。理论上这个方案是可行的,那实际各硬件的使用方式分别是怎么样的呢?

USB接口

在应用程序中与USB硬件的交互,系统提供了两种方式,包括将该应用程序所在设备的USB接口作为主机模式,和该应用程序所在设备的USB接口作为配件模式。在主机模式下,该应用程序所在设备通过USB接口为其他接入的USB设备供电,通常连接没有自带电源的设备(比如U盘)时启用此种模式;反之在配件模式下,是该应用程序所在设备接收通过USB接口接入的其他USB设备的电源提供,通常在连接有电源的设备(比如笔记本电脑)时启用此模式。理论上这两种模式只是针对USB硬件的供电方不同而区分,均可以在USB接口连接的两个设备之间的数据传输。

主机模式

权限声明

在应用程序的清单文件中,需要声明<uses-feature />标签,并设置其属性android:name值为"android.hardware.usb.host"。该标签设置并不是通过应用程序向系统申请权限,而是声明应用程序需要使用USB主机模式。

使用流程
获取USB主机设备

主机模式下,其中一种常用情况,应用程序可以监听插入USB接口的设备,此时可以在需要监听的界面Activity对应的清单文件注册信息中增加指定的接收意图,意图值为android.hardware.usb.action.USB_DEVICE_ATTACHED。这样在USB设备接入后,系统会发送上述意图值的广播,从而启动当前界面Activity

在启动后的界面Activity中,可以调用getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE)系列方法,获取android.hardware.usb.UsbDevice USB设备类的对象。

主机模式下另外一种情况,是直接获取已连接的USB设备。在能获取上下文环境Context对象的地方,调用该对象的getSystemService(String name),并指定参数值 nameContext.USB_SERVICE="usb",获得android.hardware.usb.UsbManagerUSB管理类的对象。调用该对象的getDeviceList()方法,返回List<UsbDevice>,同样能获取到当前设备连接的所有USB硬件对象的列表数据。

在直接获取已连接USB设备的情况下,应用程序需要主动向用户申请设备通信权限。通过USBManager设备管理类对象的requestPermission(UsbAccessory accessory, PendingIntent pi)方法,在用户同意授权后,才能继续后续设备通信操作。

USB设备通信

在拿到UsbDevice类型的USB设备类对象,和UsbManager管理类对象之后,调用USB管理类对象的openDevice(UsbDevice device)方法,得到android.hardware.usb.UsbDeviceConnection USB设备连接对象,其参数 device 便是要通信的USB设备对象。

建立UsbDeviceConnection设备连接对象后,通信过程中还需要分别借助android.hardware.usb.UsbInterface USB接口类和android.hardware.usb.UsbEndpoint USB端点类。

在获取UsbDevice类型的设备类对象后,调用其getInterface(int index)方法获取UsbInterfaceUSB接口类对象,其中参数 index 是当前USB设备可获取的所有接口数量中的索引值,而获取UsbDevice的所有接口数量,可根据另外一个方法getInterfaceCount()查看。

在获取UsbInterface类型的接口对象后,调用其getEndpoint(int index)方法获取UsbEndpointUSB端点类对象,其中参数 index 是当前USB接口中可获取的所有断点数量中的索引值,而获取UsbInterface的所有断点数量,可根据另外一个方法getEndpointCount()查看。

通过梅开二度获取USB接口对象和USB端点对象之后,首先要占用USB设备资源。继续调用UsbDeviceConnection连接对象的claimInterface(UsbInterface intf, boolean force)方法,其中参数 intf 便是上文获取UsbInterface接口类对象,参数 force 标明是否强制占用。返回boolean类型的结果表示占用是否成功。

在占用USB设备资源之后,就可以接收USB设备的通信数据了。调用UsbDeviceConnection连接对象的bulkTransfer (UsbEndpoint endpoint, byte[] buffer, int offset, int length, int timeout)方法。参数 endpoint 便是上文获取UsbEndpoint端点类对象;参数 buffer 用以存储通信中的二进制数组;参数 offset 可选项,默认值为0,用以标记存放数组 buffer 的起始位置;参数 length 用以标记存放数组的长度;参数 timeout 作为通信连接的最大时长。返回通信过程中实际传输的数据长度。

通信结束后,只需要关闭连接并释放占用的设备资源。调用UsbDeviceConnection连接对象的close()方法可以关闭通信连接。而调用该对象的releaseInterface(UsbInterface intf)方法可以释放占用的UsbInterface设备接口类型的参数 intf 对象。

配件模式

权限声明

在应用程序的清单文件中,需要声明<uses-feature />标签,并设置其属性android:name值为"android.hardware.usb.accessory"。该标签设置并不是通过应用程序向系统申请权限,而是声明应用程序需要使用USB配件模式。

使用流程
获取USB配件

配件模式下,其中一种常用情况,应用程序可以监听插入USB接口的设备,此时可以在需要监听的界面Activity对应的清单文件注册信息中增加指定的接收意图,意图值为android.hardware.usb.action.USB_ACCESSORY_ATTACHED。这样在USB设备接入后,系统会发送上述意图值的广播,从而启动当前界面Activity

在启动后的界面Activity中,可以调用getIntent().getParcelableExtra(UsbManager.EXTRA_ACCESSORY)系列方法,获取android.hardware.usb.UsbAccessory USB配件类的对象。

同样在配件模式下另外一种情况,是直接获取已连接的USB配件。在能获取上下文环境Context对象的地方,调用该对象的getSystemService(String name),并指定参数值 nameContext.USB_SERVICE="usb",获得android.hardware.usb.UsbManagerUSB管理类的对象。调用该对象的getAccessoryList()方法,返回List<UsbAccessory>,同样能获取到当前设备连接的所有USB配件对象的列表数据。

与主机模式类似,在直接获取已连接USB配件的情况下,应用程序需要主动向用户申请设备通信权限。通过USBManager设备管理类对象的requestPermission(UsbAccessory accessory, PendingIntent pi)方法,在用户同意授权后,才能继续后续设备通信操作。

USB设备通信

在拿到UsbAccessory类型的USB配件类对象,和UsbManager管理类对象之后,调用USB管理类对象的openAccessory(UsbAccessory accessory)方法,得到android.os.ParcelFileDescriptor 数据流化的文件描述符类的对象,其参数 accessory 便是要通信的USB配件对象。

在获取ParcelFileDescriptor数据流化的文件描述符类的对象后,调用其getFileDescriptor()方法得到java.io.FileDescriptor普通的文件描述符类型的对象,之后通过该对象创建基本的文件输入流java.io.FileInputStream对象以读取USB配件中的数据,或者创建基本的文件输出流java.io.FileOutputStream对象以将数据写入USB配件中。

通信结束后,只需要关闭数据流化的文件描述符的占用即可。通过调用ParcelFileDescriptor对象的close()方法以实现该操作。

主机模式与配件模式的区别

代码软件层

主机模式下,主要使用UsbDevice类,可以获取所连接USB设备的详细信息。

配件模式下,只能使用UsbAccessory类,只能获取连接USB设备的基本信息。

硬件层

主机模式下,由应用程序所在的设备向主线供电,并向连接的USB设备供电。

配件模式下,由连接的USB设备作为主机向主线供电,并向应用程序所在的设备供电。

Android系统编程入门系列之硬件交互——通信硬件USB的更多相关文章

  1. Android系统编程入门系列之加载界面Activity

    上回说到应用初始化加载及其生命周期,在Android系统调用Applicaiton.onCreate()之后,继续创建并加载清单文件中注册的首个界面即主Activity,也可称之为入口界面.主Acti ...

  2. Android系统编程入门系列之硬件交互——多媒体摄像头

    多媒体系列硬件 多媒体包括图片.动画.音频.视频,这些多媒体素材的采集(输入)主要依靠摄像头和麦克风等硬件设备转化为基础数据,而他们的播放渲染(输出),则需要依靠具有相关功能的编解码软件.当然随着硬件 ...

  3. Android系统编程入门系列之硬件交互——传感器

    到目前为止,关于应用程序与用户之间的相关内容便比较肤浅的大致介绍完毕.而在整个系统架构中,应用程序与用户之间的交互,犹如参天大树上的枝干和树叶,交互起来五彩缤纷,但使整个生态系统保持生命力的核心,在于 ...

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

    通信硬件NFC的文章,虽然可以在Android系统中通过非直接接触的形式与支持NFC硬件的设备通信,但是也只能交互一些简短的标签内容,对大量的持续性数据,却并不能很好的支持.因此针对这个弊端,可以考虑 ...

  5. Android系统编程入门系列之硬件交互——多媒体展示

    前两篇文章通过麦克风硬件和摄像头硬件分别采集音频和视频的多媒体数据,在得到的多媒体数据通常是以编码文件的格式存储,在用户需要展示时,可通过设备的内置扩音器或蓝牙耳机等硬件播放音频,通过设备的显示屏或外 ...

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

    在上篇文章介绍了接入式USB硬件的简单使用,接下来将介绍不依赖物理连接的硬件通信了.本文的重点是近距离通信的硬件NFC. NFC硬件 应用程序中可以通过NFC硬件读取或发送指定协议的技术实现,在And ...

  7. Android系统编程入门系列之硬件交互——无线通信WLAN

    Android系统的移动设备大多支持无线WLAN技术.利用该技术,不仅能实现互联网通信,还能实现无线定位,热点共享等远程通信功能.针对使用WLAN的不同功能,可能需要分别申请不同的权限声明,同时调用不 ...

  8. Android系统编程入门系列之硬件交互——通信硬件电信SIM卡

    现在的SIM卡通常具备基站定位.语音通话.短信消息.网络流量这四大功能,而在移动端是无法对SIM卡使用基站定位功能的,所以这里只介绍移动端如何使用SIM卡实现语音通话.短信消息.数据流量三个功能. 语 ...

  9. Android系统编程入门系列之界面Activity交互响应

    在上篇文章中已经了解到界面Activity的绘制完全依赖其加载的视图组件View,不仅如此,用户的每次触摸操作都可以在界面Activity内接收并响应,也可以直接传递给其中的某个视图View响应.本文 ...

随机推荐

  1. C#获取Windows10屏幕的缩放比例

    现在1920x1080以上分辨率的高分屏电脑渐渐普及了.我们会在Windows的显示设置里看到缩放比例的设置.在Windows桌面客户端的开发中,有时会想要精确计算窗口的面积或位置.然而在默认情况下, ...

  2. 【代码优化】List.remove() 剖析

    一.犯错经历 1.1 故事背景 最近有个需求大致的背景类似: 我已经通过一系列的操作拿到一批学生的考试成绩数据,现在需要筛选成绩大于 95 分的学生名单. 善于写 bug 的我,三下五除二完成了代码的 ...

  3. 远程调用RPC

    一.简介 RPC,就是Remote Procedure Call的简称呀,翻译成中文就是远程过程调用. 本地调用,就好比你现在在家里,你要想洗碗,那你直接把碗放进洗碗机,打开洗碗机开关就可以洗了.这就 ...

  4. Nginx配置FTP

    目录 一.简介 二.配置 一.简介 ftp有单独的服务,但配置并不轻松.相对于比较熟悉的nginx,做ftp要容易很多. 二.配置 添加一个server字段 server { listen 8888; ...

  5. Python 的切片为什么不会索引越界?

    切片(slice)是 Python 中一种很有特色的特性,在正式开始之前,我们先来复习一下关于切片的知识吧. 切片主要用于序列对象中,按照索引区间截取出一段索引的内容. 切片的书写形式:[i : i+ ...

  6. zabbix保姆级安装教程

    安装步骤 1.进入官网选择下载的版本和服务器类型 官网地址:https://www.zabbix.com/cn/download?zabbix=5.0&os_distribution=cent ...

  7. MVC中的打印功能

    HTML页面: @{ Layout = "~/Views/Shared/_IframeLayout.cshtml";}@Scripts.Render(ViewBag.ScriptP ...

  8. 【LeetCode】203. Remove Linked List Elements 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 递归 日期 题目地址:https://lee ...

  9. 【LeetCode】303. Range Sum Query - Immutable 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 保存累积和 日期 题目地址:https://leetcode. ...

  10. 【LeetCode】116. 填充每个节点的下一个右侧节点指针 Populating Next Right Pointers in Each Node 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...