OTG在Android3.1及以上被支持。也就是minSdkVersion为12.

API概述

UsbManager
允许您枚举已连接的USB设备并且与其进行“交流”。

UsbDevice
代表了一个已连接的USB的设备并且包含具有该设备验证信息,接口和接入点的方法。

UsbInterface
代表了一个USB设备的一个接口,该接口定义了一系列关于设备的函数。一个设备在进行“交流”的时候可以有一个或者多个接口。

UsbEndpoint
代表一个接口的接入点,该接入点就是这个接口的通信信道。一个接口可以有一个或者多个这样的接入点,而且一般都是有输入和输出双向通信的接入点。

UsbDeviceConnection
代表该设备的一个连接,用来在接入点上传输数据。这个类允许您能用同步或者异步的方式发送和返回数据。

UsbRequest
在通过UsbDeviceConnection和设备进行“交流”的一个异步请求。

UsbConstants
关于在linux内核中linux/usb/ch9.h的相关定义的USB常量。

在大多数情况中,跟USB设备通信时,需要使用所有这些类(使用异步通信,只需要使用UsbRequest类)。使用UsbManager对象来获取期望的UsbDevice对象。有了这个UsbDevice对象时,就需要查找对应的UsbInterface对象和基于该接口通信的UsbEndpoint对象。一旦获取了正确的端点,就可以打开UsbDeviceConnect对象来跟USB设备进行通信了。

Android清单要求

在使用USB主机模式API工作之前,你需要把以下介绍的内容添加到你的应用程序清单中:

1. 因为不是所有的Android设备都保证支持USB主机模式,所以要在你的应用程序声明中包含元素,以声明你的应用程序要使用android.hardware.usb.host功能。

2. 把应用程序的最小SDK设置为API Level 12或更高的版本。在较早的API版本中不存在USB主机模式API。

3. 如果你希望你的应用程序能够获得接入USB设备时的通知,那么还要在你的主Activity中指定用android.hardware.usb.action.USB_DEVICE_ATTACHED类型的Intent来配对的和元素。元素要指向一个外部的XML资源文件,该文件声明了希望检测的设备的识别信息。

在这个XML资源文件中,要用元素来声明你想要过滤的USB设备。以下列出了元素的属性。通常,使用vendor-id和product-id来指定你所希望过滤的特定的设备,并且使用class、subclass和protocol来指定你所希望过滤的USB设备组,如大容量存储设备或数码相机。你可以不指定任何属性,或所有全部属性。不指定任何属性,就会跟所有USB设备匹配,如果应用程序需要,就可以这样做:

A. vendor-id

B. product-id

C. class

D. subclass

E. protocol(设备或接口)

在res/xml目录中保存这个资源文件。该资源文件的名称(不含.xml扩展名)必须跟元素中指定的名称相同。XML资源文件的格式请看下例。

1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3     package="com.example.testusb"
4     android:versionCode="1"
5     android:versionName="1.0"
6     >
7  
8     <uses-sdk
9         android:minSdkVersion="12"
10         android:targetSdkVersion="17" />
11      
12     <uses-feature android:name="android.hardware.usb.host" />
13  
14     <application
15         android:allowBackup="true"
16         android:icon="@drawable/ic_launcher"
17         android:label="@string/app_name"
18         android:theme="@style/AppTheme" >
19         <activity
20             android:name="com.example.testusb.TestUSB"
21             android:label="@string/app_name" >
22             <intent-filter>
23                 <action android:name="android.intent.action.MAIN" />
24                 <category android:name="android.intent.category.LAUNCHER" />
25             </intent-filter>
26             <!-- 当你需要希望你的应用能够被连接的设备所提示,需要针对intent-filter和meta-data加上android.hardware.usb.action.USB_DEVICE_ATTACHED意图 -->
27             <intent-filter>
28                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
29             </intent-filter>
30  
31             <!-- 用于过滤具体USB设备,其中device_filter是个xml文件 -->
32             <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
33                 android:resource="@xml/device_filter" />
34         </activity>
35          
36     </application>
37  
38 </manifest>

资源文件应该保存在res/xml/device_filter.xml

查看源代码 打印帮助
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3     <!-- 如果你不确定你需要检测的设备vendor-id和product-id,可以所有的参数都为空,将获得所有已连接的USB设备。
4     否则请对应上相应参数。 -->
5     <usb-device vendor-id="65535" product-id="65535" class="255" subclass="66"protocol="1" />
6 </resources>

可以在Windows上查看USB设备的VID和PID,需要注意的是,在Windows上VID和PID都是十六进制数,需要转换为10进制。

声明: 本文由( 上善若水 )原创编译,转载请保留链接: OTG – Android USB Host(一)

发现设备
可以使用两种方法来发现设备:
1.使用Intent过滤器,过滤用户接入USB设备时所发出的通知;
2.列举已经接入的USB设备。

如果你希望你的程序能够自动的检测你所期望的USB设备,需要使用Intent过滤器,如我们刚才在AndroidManifest.xml中添加的过滤器。

在Activity中,可以从这样的意图中获取UsbDevice:

1 UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

如果你你希望过滤所有的USB设备,或者应用程序没有过滤对应的Intent对象,那么可以使用列举:

1 UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
2 HashMap<String, UsbDevice> map = usbManager.getDeviceList();
3 for(UsbDevice device : map.values()){
4     Log.i(TAG, "dName: " + device.getDeviceName());
5     Log.i(TAG, "vid: " + device.getVendorId() + "\t pid: " + device.getProductId());
6     usbDevice = device;
7     //Other code
8 }

或者使用迭代,获取每一个设备:

1 HashMap<String, UsbDevice> deviceList = usbManager .getDeviceList();
2 Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
3 while(deviceIterator.hasNext()){
4     UsbDevice device = deviceIterator.next();
5     //Other code
6 }

获取跟设备通信的权限
在跟USB设备进行通信之前,你的应用程序必须要获取用户的许可。
注意:如果你的应用程序使用Intent过滤器来发现接入的USB设备,而且用户允许你的应用程序处理该Intent,那么它会自动的接收权限,否则,在你的应用程序接入该设备之前,必须明确的申请权限。

明确的申请权限在某些情况下是必须的,如你的应用程序列举已经接入的USB设备并想要跟其中的一个设备通信的时候。在试图跟一个设备通信之前,你必须要检查是否有访问设备的权限。否则,如果用户拒绝了你访问该设备的请求,你会收到一个运行时错误。

要明确的获取这个权限,首先要创建一个广播接收器。这个接收器用于监听你调用requestPermission()方法时,系统所发出的Intent对象。调用requestPermission()方法时,系统会显示一个对话框,询问用户是否允许跟该USB设备进行连接。下列代码演示如何创建这个广播接收器:

1 private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
2 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
3  
4     public void onReceive(Context context, Intent intent) {
5     String action = intent.getAction();
6         Log.e(TAG, action);
7              
8     if (ACTION_USB_PERMISSION.equals(action)) {
9         synchronized (this) {
10         usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
11         //允许权限申请
12         if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
13             if(usbDevice != null){
14                 //call method to set up device communication
15                 }
16             else {
17                 Log.d(TAG, "permission denied for device " + usbDevice);
18             }
19         }
20     }
21 };

注册接收的广播,并放在onCreate中:

1 //注册广播
2 IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
3 registerReceiver(mUsbReceiver, filter);

申请权限:

1 PendingIntent pi = PendingIntent.getBroadcast(this0new Intent(ACTION_USB_PERMISSION),0);
2 if(usbManager.hasPermission(usbDevice)){
3     //Other code
4 }else{
5     //没有权限询问用户是否授予权限
6     usbManager.requestPermission(usbDevice, pendingIntent); //该代码执行后,系统弹出一个对话框,
7                                                             //询问用户是否授予程序操作USB设备的权限
8 }

当用户回应这个对话框时,你的广播接收器就会收到一个包含用一个boolean值来表示结果的EXTRA_PERMISSION_GRANTED字段的意图。在您连接设备之前检查这个字段的值是否为true。

跟设备进行通信:
我们可以同步或者异步的和USB设备进行“交流”。在任意一种情况之下,您都应该创建一个新的线程来进行数据传输,这样就不会阻塞您的主线程了。要想正确的设置好和一个设备之间的连接,您需要获得该设备正确的UsbInterface和UsbEndpoint来和您进行“交流”以及通过UsbDeviceConnection在这个接入点上发送请求。一般来说,您的代码应该这样:

1.检查一个UsbDevice对象的属性,例如产品ID,供应商ID,或者是关于设备的类,以此来确认您是否希望和该设备进行“交流”。

2.当您确信您希望和该设备进行“交流”时,找到关于该设备正确的UsbInterface以及和该接口所对应的UsbEndpoint。接口可以有一个或者多个接入点,而且一般都会有一个双向通信的输入和输出接入点。

3.当您找到正确的接入点时,在该接入点时打开一个UsbDeviceConnection。

4.您可以通过bulkTransfer()和controlTransfer()这两个方法在接入点上传输您所需要传递的数据。您最好在另起一个新的线程来进行这个步骤以避免阻塞主线程。想要详细地了解关于Android中使用线程的信息,详见线程和进程。

1 private Byte[] bytes;
2 private static int TIMEOUT = 3000;
3 private boolean forceClaim = true;
4  
5 UsbInterface usbInterface = usbDevice.getInterface(0);
6 //USBEndpoint为读写数据所需的节点
7 UsbEndpoint inEndpoint = usbInterface.getEndpoint(0);  //读数据节点
8 UsbEndpoint outEndpoint = usbInterface.getEndpoint(1); //写数据节点
9 UsbDeviceConnection connection = usbManager.openDevice(usbDevice);
10 connection.claimInterface(usbInterface, true);
11              
12 //发送数据
13 byte[] byte2 = new byte[64];    //发送与接收字节数与设备outputreport有关
14 int out = connection.bulkTransfer(outEndpoint, bytes, bytes.length, TIMEOUT);
15 Log.e(TAG, "out:" + out);
16              
17 //读取数据1   两种方法读取数据
18 int ret = connection.bulkTransfer(inEndpoint, byte2, byte2.length, TIMEOUT);
19 Log.e(TAG, "ret:"+ret);
20  
21 //还有第二种读取方式,未验证。
22 int outMax = outEndpoint.getMaxPacketSize();
23 int inMax = inEndpoint.getMaxPacketSize();
24 ByteBuffer byteBuffer = ByteBuffer.allocate(inMax);
25 UsbRequest usbRequest = new UsbRequest();
26 usbRequest.initialize(connection, inEndpoint);
27 usbRequest.queue(byteBuffer, inMax);
28 if(connection.requestWait() == usbRequest){
29     byte[] retData = byteBuffer.array();
30 }

终止通信:

当您在完成和设备的“交流”之后,又或者该设备被移除了,通过调用releaseInterface()和close()的方法来关闭UseInterface和UsbDeviceConnection。为了监听分离这样的事件,您需要创建一个如下的广播接收器:

1 BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
2     public void onReceive(Context context, Intent intent) {
3         String action = intent.getAction();
4   
5       if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
6             UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
7             if (device != null) {
8                 // call your method that cleans up and closes communication with the device
9             }
10         }
11     }
12 };

在您的应用中创建这个广播接收器,不是在manifest文件中,允许您的应用只能在它运行的时候处理这样的设备分离事件。这样的话,设备分离这个事件就只向正在运行的应用广播,而不是向所有的应用进行广播。

总结:

我在发送数据的时候,返回的是2,接收返回-1,一直不清楚需要发送的数据是什么格式需要哪些命令,在网上查找了很久也没有找到。
也就只能做到设备接通,但是通信不算成功。

暂时没有时间深入研究了,有兴趣的同学可以查看一下Android的示例代码:Adb test sample,显示了怎样进行异步块数据数据传输,MissleLauncher sample显示了如何监听异步的中断端点。

声明: 本文由( 上善若水 )原创编译,转载请保留链接: OTG – Android USB Host(三)

OTG – Android USB Hos相关推荐

  1. Android OTG (USB Hos) 编程

    前言:最近在做一个汽车发动机故障检测的项目,负责APP开发.汽车发动机将各种数据通过OTG传输到Android手机,APP可以实时显示数据. 一.权限 1. 声明支持USB Hos模式 在Androi ...

  2. android usb otg,android usb otg需要什么权限

    USB OTG功能如何打开及实现 USB OTG U盘 Keyboard Mouse 1.检查HW原理图,确认是否支持OTG功能(vbus是否供上电,IDDIG pin连接是否正确) 若HW确认支持O ...

  3. Android USB OTG U盘读写相关使用最全总结

    Android USB OTG U盘读写相关使用最全总结 https://blog.csdn.net/qq_29924041/article/details/80141514 androidOTG ( ...

  4. Android usb otg通讯总结 HiD通讯直接来取吧

    最近在搞一个Android的通过otg与设备进行usb通讯的功能HID. 过程中遇到了一个大坑,就是usb发数据的时候,第一次显示发送成功(返回值大于1),但是设备并没有收到实际的数据,把usb重新拔 ...

  5. 基于AOA协议的android USB通信

    摘 要:AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议.该协议拓展了Android设备USB接口的功能,为基于Android系统的智能设备应用于数据采集和设 ...

  6. Android USB转串口编程

    安卓手机的对外通信接口就只有USB跟音频口,我们可采用其进行与外设进行通信.今天,我们来讲讲安卓手机利用USB接口与外设进行通信.此时,有两种情况. 第一:USB(手机)<--->USB( ...

  7. Android+usb+spi,Android设备如何使用USB的硬件接口

    你知道Android设备如何使用USB的硬件接口吗?下面将由学习啦小编带大家来解答这个疑问吧,希望对大家有所收获! 如何处理硬件接口问题 最近业界的发展显示,智能手机/便携系统与自动化系统或机械系统之 ...

  8. android usb 手柄吃鸡,游戏手柄怎么用,吃鸡游戏手柄怎么用

    如何使用游戏手柄 游戏中还有设置选项,通常需要将"键盘"更改为"手柄". 我买了游戏手柄,如何使用? _ 分析如下:1.看一下控制面板,控制面板上的硬件和声音设 ...

  9. android usb gadget分析

    Android USB驱动中,上层应用协议里最重要的一个文件是android/kernel/drivers/usb/gadget/android.c.这个文件实现USB的上层应用协议. 首先包含了一些 ...

最新文章

  1. ucontext实现的用户级多线程框架3(实现echo服务器)
  2. GO语言有哪些优势?怎样入门?
  3. 数学问题当中的一些基本计数问题
  4. win10子系统linux编译ffmpeg
  5. 美国新WiFi技术功耗低于蓝牙LE和Zigbee
  6. 微信web-view 开发_在不到7个月的时间里我如何成为一名Web开发人员-以及如何
  7. 计算机视觉论文-2021-07-06
  8. Fiddler之文件代理
  9. redhat solutions
  10. burpsuite的基本操作_burpsuite安装与基本使用
  11. GPS NMEA码详解
  12. java --运用hhs 框架,tomcat 访问mysql 数据库 连接 失败后,自动 重新连接怎么做?
  13. 分享一下前几个月我做的超炫的登录页面
  14. Live2D_2.X基本功能
  15. python实现生日悖论分析
  16. 运行项目报错 proxy error: could not proxy request...
  17. PHP Fatal error: Uncaught Error: Class ‘\Elasticsearch\Serializers\SmartSerializer‘ not found in /h
  18. 解读IPD流程体系的“三驾马车”
  19. 七:Grafana-Sierra Plot用法
  20. 海外服务器CDN加速与双线服务器有什么不同?

热门文章

  1. php判断区间数字,如何快速判断数字在那个区间?
  2. Python数据分析之商品数据分析
  3. DSPE-Thiol; DSPE-SH; 二硬脂酰磷脂酰乙醇胺改性巯基
  4. 常见的计算机专业的复合命题例子,第五章、复合命题.ppt
  5. 必应词典英语学习APP案例分析
  6. 贵州建筑施工劳务资质备案流程
  7. 企业增强型融合通讯解决方案Cnskype
  8. 七年级上册教材同步英语笔记
  9. android+微信支付
  10. iPhone--什么是解锁