Android USB 开发详解

先附上 Android USB 官方文档

Android通过两种模式支持各种 USB 外设和 Android USB 附件(实现Android附件协议的硬件):USB附件和USB主机。USB开发需 Android 3.1(API级别12)以上。由于本人工作中只用到了主机模式,所以本文的侧重点在主机模式开发。

调试

在使用 USB 连接设备调试的时候,USB 外设将不能连接至设备,可以使用 WIFI 的方式连接调试,settings -> plugin -> WiFi ADB 插件好几个,选个适合自己的就 OK。

或者…我这里正好有一篇Android 模拟器连接 USB 设备喜欢点个赞哈!

一、AndroidManifest 文件设置

  • uses-feature 申明这个软件需要使用 USB 功能,申明这个 Google Play 会把不满足的设备过滤掉,一般用 USB 的都是定制开发,忽略就行
<uses-feature android:name="android.hardware.usb.host"/>
  • 1
  • 将应用程序的最低SDK设置为API级别12或更高,早期 API 没有。
  • 如果你希望你的应用程序连接指定的 USB 设备时被通知,需指定 和 元素对用于 android.hardware.usb.action.USB_DEVICE_ATTACHED。该 元素指向声明识别有关您要检测的设备信息的外部XML资源文件。
<activity
android:name=".MainActivity"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- 如果这里是启动 Activity 的话,点击 USB 接入的弹窗会启动该页面 -->
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
  • 在XML资源文件中,声明要过滤的USB设备的元素。以下列表描述了属性 。通常,如果要过滤特定设备并使用类,子类和协议(如果要过滤一组USB设备(如大容量存储设备或数码相机)),请使用供应商(vendor-id)和产品(product-id)ID,在开发中这些过滤ID一般可以在文档中找到,或者自己连上看也行。你可以指定部分或全部这些属性。
    将资源文件保存在res/xml/目录中。资源文件名(不带.xml扩展名)必须与您在元素中指定的文件名相同 。对于XML资源文件格式的 例子如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device
class="255"
product-id="5678"
protocol="1 "
subclass="66"
vendor-id="1234" />
</resources>

配置好清单文件后当用户连接与您的设备过滤器匹配的设备时,系统会向他们显示一个对话框,询问他们是否要启动您的应用程序。如果用户接受,则应用程序将自动具有访问设备的权限,直到设备断开连接。如果给了默认,那么这个 USB 设备插入后会自动启动这个 Activity

二、USB 设备的连接和使用

在清单文件中配置好以后我们直接进入 Java 代码环节

1.Android 中的 USB

Android 3.1(API级别12)以上原生提供了 USB 开发的 API,在android.hardware.usb包下提供了开发的相关类。

Class 说明
UsbManager 获得 USB 管理器,与连接的 USB 设备通信。
UsbDevice USB 设备的抽象,每个UsbDevice 都代表一个 USB 设备。
UsbInterface 定义了设备的功能集,一个 UsbDevice 可能包含一个或多个UsbInterface,每个 Interface 都是独立的。
UsbEndpoint UsbEndpoint 是 interface 的通信通道。
UsbDeviceConnection host 与 device 建立的连接,并在 endpoint 传输数据。
UsbRequest USB 请求包。
UsbConstants USB 常量的定义

2.USB 设备的插入

Android 系统中,USB 设备的插入和拔出是以系统广播的形式发送的,我们只要注册监听这个广播就好

public class USBReceiver extends BroadcastReceiver {
public static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; @Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
// 获取权限结果的广播
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
//call method to set up device communication
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
Log.e("USBReceiver", "获取权限成功:" + device.getDeviceName());
} else {
Log.e("USBReceiver", "获取权限失败:" + device.getDeviceName());
}
}
}
}else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
// 有新的设备插入了,在这里一般会判断这个设备是不是我们想要的,是的话就去请求权限
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
// 有设备拔出了
}
}
}

3.获取 UsbManager

usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

4.获取 USB 设备列表

    public List<UsbDevice> getDeviceList() {
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
List<UsbDevice> usbDevices = new ArrayList<>();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
usbDevices.add(device);
Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());
}
return usbDevices;
}

5.获取特定的设备

    /**
* mVendorId=1137,mProductId=85 佳博 3150T 标签打印机
*
* @param vendorId 厂商ID
* @param productId 产品ID
* @return device
*/
public UsbDevice getUsbDevice(int vendorId, int productId) {
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
if (device.getVendorId() == vendorId && device.getProductId() == productId) {
Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());
return device;
}
}
Toast.makeText(context, "没有对应的设备", Toast.LENGTH_SHORT).show();
return null;
}

6.申请 USB 设备使用权限

安卓系统对 USB 设备的使用需要得到相应的权限,这个权限要用户手动授予,或插入设备时应用到你的应用中。在使用 USB 设备前首先我们要确认一下上一节中的device是否已经获得权限,如果没有就要主动申请权限:

    /**
* 判断对应 USB 设备是否有权限
*/
public boolean hasPermission(UsbDevice device) {
return usbManager.hasPermission(device);
} /**
* 请求获取指定 USB 设备的权限
*/
public void requestPermission(UsbDevice device) {
if (device != null) {
if (usbManager.hasPermission(device)) {
Toast.makeText(context, "已经获取到权限", Toast.LENGTH_SHORT).show();
} else {
if (mPermissionIntent != null) {
usbManager.requestPermission(device, mPermissionIntent);
Toast.makeText(context, "请求USB权限", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "请注册USB广播", Toast.LENGTH_LONG).show();
}
}
}
}

注册广播:

    public void registerReceiver(Activity context) {
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
context.registerReceiver(usbReceiver, filter);
}

7.通信

与 USB 设备的通信可以是同步的也可以是异步的。无论哪种情况,你都应该创建一个新线程来执行所有数据传输,避免阻塞UI线程。

第一步,打开通信端口

    public boolean openPort(UsbDevice device) {
//获取设备接口,一般只有一个,多个的自己研究去
usbInterface = device.getInterface(0); // 判断是否有权限
if (hasPermission(device)) {
// 打开设备,获取 UsbDeviceConnection 对象,连接设备,用于后面的通讯
usbConnection = usbManager.openDevice(device); if (usbConnection == null) {
return false;
}
if (usbConnection.claimInterface(usbInterface, true)) {
Toast.makeText(Utils.getContext(), "找到 USB 设备接口", Toast.LENGTH_SHORT).show();
} else {
usbConnection.close();
Toast.makeText(Utils.getContext(), "没有找到 USB 设备接口", Toast.LENGTH_SHORT).show();
return false;
}
} else {
Toast.makeText(Utils.getContext(), "没有 USB 权限", Toast.LENGTH_SHORT).show();
return false;
} //获取接口上的两个端点,分别对应 OUT 和 IN
for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
UsbEndpoint end = usbInterface.getEndpoint(i);
if (end.getDirection() == UsbConstants.USB_DIR_IN) {
usbEndpointIn = end;
} else {
usbEndpointOut = end;
}
}
return true;
}

第二步,发送数据

usbConnection.bulkTransfer(usbEndpointOut, bytes, bytes.length, 500);

其他

剩余的 API 我会在项目不断完善的同时更新上来

附:demo 传送门

Android USB 开发详解的更多相关文章

  1. Android WebView 开发详解

    Android WebView 开发详解 参见 http://blog.csdn.net/typename/article/details/39030091

  2. JMessage Android 端开发详解

    目前越来越多的应用会需要集成即时通讯功能,这里就为大家详细讲一下如何通过集成 JMessage 来为你的 App 增加即时通讯功能. 首先,一个最基础的 IM 应用会需要有哪些功能? 用户注册 / 登 ...

  3. 《Android游戏开发详解》一1.7 控制流程第1部分——if和else语句

    本节书摘来异步社区<Android游戏开发详解>一书中的第1章,第1.7节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.7 ...

  4. Android WebView 开发详解(一)

    转载请注明出处  http://blog.csdn.net/typename/article/details/39030091 powered by meichal zhao 概览: Android ...

  5. Android Widget 开发详解(二) +支持listView滑动的widget

    转载请标明出处:http://blog.csdn.net/sk719887916/article/details/47027263 不少开发项目中都会有widget功能,别小瞧了它,他也是androi ...

  6. Android WebView 开发详解(三)

    转载请注明出处   http://blog.csdn.net/typename/article/details/40302351 powered by miechal zhao 概览 Android ...

  7. Android WebView 开发详解(二)

    转载请注明出处  http://blog.csdn.net/typename/article/details/39495409 powered by miechal zhao   概览: Androi ...

  8. 【转】【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料

    转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9057257 由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字 ...

  9. 【Android应用开发详解】实现第三方授权登录、分享以及获取用户资料

      由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo.实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相 ...

随机推荐

  1. UISegmentedControl的具体使用

    当用户输入不不过布尔值时.可使用分段控件(UISegmentedControl).分段控件提供一栏button(有时称为button栏),但只能激活当中一个button. 分段控件会导致用户在屏幕上看 ...

  2. hadoop 使用和javaAPI

    hadoop的安装,见http://www.powerxing.com/install-hadoop/,简略版教程见http://www.powerxing.com/install-hadoop-si ...

  3. 谈 API 的撰写 - 总览

    背景 之前团队主要的工作就是做一套 REST API.我接手这个工作时发现那些API写的比较业余,没有考虑几个基础的HTTP/1.1 RFC(2616,7232,5988等等)的实现,于是我花了些时间 ...

  4. OCP学习基本知识点总结

     下面是我总结的OCP教程的知识点.以备參考之用. 1, What's Oracle Server? ·         It's a database management system that ...

  5. Cardboard虚拟现实开发初步(一)

    Google Cardboard 虚拟现实眼镜开发初步(一) 虚拟现实技术简单介绍 不得不说这几年虚拟现实技术逐渐火热,伴随着虚拟现实设备的价格迅速平民化,越来越多的虚拟现实设备来到了我们眼前,也因此 ...

  6. linux 挂载相关

    mount命令的用法,以及技巧光盘镜像文件.移动硬盘.共享文件夹及U盘的方法. 一,挂接命令(mount) 挂接(mount)命令的使用方法. 命令格式:  mount [-t vfstype] [- ...

  7. CSS解决无空格太长的字母,数字不会自己主动换行的问题

    事实上非常easy,代码例如以下所看到的,注意 Style: <div class="detail_title" style="word-break: break- ...

  8. 开发ActiveX控件调用另一个ActiveX系列0——身份证识别仪驱动的问题

    程序员要从0下表开始,这篇是介绍这个系列的背景的,没有兴趣的人可以直接跳过. 为什么要开发ActiveX控件 由于工作需要,我们开发了一个网站,使用了一款身份证识别仪的网页ActiveX(OCX)插件 ...

  9. jquery插件中使用ajax并且获取使用插件的对象

    jquery插件中使用ajax后无法在里面获取this 解决办法是在函数内使用ajax前声明变量 $this=this 然后再ajax中使用$this

  10. erlang程序优化点的总结

    注意,这里只是给出一个总结,具体性能需要根据实际环境和需要来确定 霸爷指出,新的erlang虚拟机有很多调优启动参数,今后现在这个方面深挖一下. 1. 进程标志设置: 消息和binary内存:erla ...