草庐IT

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

星城之路 2023-03-28 原文

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

互联通信系列硬件

根据硬件的可通信距离,由近及远分为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. 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

随机推荐