在你的android设备上USB主机模式,它作为USB主机,权力的公共汽车, 并列举了USB设备连接。 USB主机模式支持Android 3.1和更高版本。
在您开始之前,重要的是要理解你所需要的类。 的 下表描述了USB主机的api android.hardware.usb
包中。
类 | 描述 |
---|---|
UsbManager |
允许你列举和与连接USB设备通信。 |
UsbDevice |
代表一个连接USB设备和包含的方法来访问它的识别 信息、接口和端点。 |
UsbInterface |
代表一个USB设备的接口,它定义了一组的功能 设备。 一个设备可以有一个或多个接口的通信。 |
UsbEndpoint |
代表一个接口端点,该接口的通信通道。 一个 接口可以有一个或多个端点,通常有输入和输出端点 双向通信的设备。 |
UsbDeviceConnection |
代表一个连接到设备,数据传输的端点。 这个类 允许你来回同步或异步发送数据。 |
UsbRequest |
代表了一个异步请求与设备通过通信 UsbDeviceConnection 。 |
UsbConstants |
对应于定义定义了USB的常量在linux / USB / ch9。 h(Linux 内核。 |
在大多数情况下,您需要使用所有这些类( UsbRequest
只是如果你需要做异步通信) 当与USB设备通信。 一般来说,你获得一个 UsbManager
来检索所需的 UsbDevice
。 当你的设备,你需要找到合适的 UsbInterface
和UsbEndpoint
的 接口通信。 一旦你获得正确的端点,打开一个 UsbDeviceConnection
与USB设备进行通信。
下面的列表描述了您需要添加到您的应用程序的清单文件 使用USB主机api:
< uses-feature >
您的应用程序使用的元素声明 的 android.hardware.usb.host
特性。<意图过滤器>
和 <元数据>
元素对的android.hardware.usb.action.USB_DEVICE_ATTACHED
你的主要活动的意图。 的 <元数据>
元素指向外部声明的XML资源文件 确定要检测的设备信息。 在XML资源文件中,申报的东西 < usb设备>
USB的元素 你想过滤设备。 下面的列表描述的属性 < usb设备>
。 一般来说,使用供应商和产品ID如果你想过滤器 为一个特定的设备和使用类、子类和协议如果你想过滤为一组 USB设备,如大容量存储设备或数码相机。 您可以指定或没有 所有这些属性。 没有匹配的属性指定每一个USB设备,所以只有这样做 如果您的应用程序要求:
卖主身份证
产品id
类
子类
协议
(设备或接口)节省的资源文件 res / xml /
目录中。 资源文件名称 (没有。 xml扩展)必须与你指定的相同 <元数据>
元素。 格式的XML资源文件 例子 在下面。
下面的示例显示了一个示例清单和相应的资源文件:
<manifest ...> <uses-feature android:name="android.hardware.usb.host" /> <uses-sdk android:minSdkVersion="12" /> ... <application> <activity ...> ... <intent-filter> <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> </application> </manifest>
在这种情况下,应该保存在下面的资源文件 res / xml / device_filter.xml
与指定的指定,任何USB设备 属性应该过滤:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" /> </resources>
当用户连接USB设备的Android设备上,Android系统可以确定 您的应用程序是否感兴趣的连接设备。 如果是这样,您可以设置 与设备如果需要沟通。 要做到这一点,您的应用程序有:
您的应用程序可以发现USB设备通过使用一个意图过滤器时收到通知 用户连接设备或通过列举USB设备已经连接。 使用一个 意图过滤器是非常有用的,如果你想应用程序能够自动检测 所需的设备。 列举连接USB设备是有用的,如果你想要所有的列表 连接设备或如果你的应用程序没有过滤的目的。
您的应用程序发现特定的USB设备,您可以指定一个意图过滤器 过滤器的android.hardware.usb.action.USB_DEVICE_ATTACHED
意图。 随着 此意图过滤器,您需要指定一个资源文件,指定属性的USB 设备,如产品和供应商ID。当用户连接的设备匹配你的设备 滤波器,系统给他们提供了一个对话框,询问如果他们想开始您的应用程序。 如果用户接受,您的应用程序自动权限访问设备,直到 设备断开连接。
下面的例子显示了如何声明意图过滤器:
<activity ...> ... <intent-filter> <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>
下面的例子展示了如何声明指定相应的资源文件 你感兴趣的USB设备:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="1234" product-id="5678" /> </resources>
在你的活动,你可以获得 UsbDevice
代表 附加设备的意图是这样的:
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
如果您的应用程序感兴趣的检查所有的USB设备当前连接 应用程序运行时,它可以枚举设备在公共汽车上。 使用getDeviceList()
方法来获取一个散列映射 连接的USB设备。 哈希映射键控的USB设备的名字,如果你想 从地图上获取一个设备。
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); ... HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); UsbDevice device = deviceList.get("deviceName");
如果需要,你也可以获得散列映射的迭代器和处理每个设备 一:
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); ... HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); while(deviceIterator.hasNext()){ UsbDevice device = deviceIterator.next(); //your code }
在与USB设备之前,应用程序必须得到你的许可 用户。
注意: 如果您的应用程序 使用一个 意图过滤器 发现他们连接USB设备,它可以自动接收 如果用户许可允许您的应用程序处理的目的。 如果没有,你必须请求 允许显式地在您的应用程序连接到设备。
明确要求许可可能是必要的在某些情况下,例如当你 应用列举了USB设备已经连接,然后想要沟通 一个。 你必须检查权限访问设备之前试图沟通。 如果 不,你将收到一个运行时错误如果用户拒绝访问设备。
显式地获得许可,首先创建一个广播接收器。 这个接收器监听 意图让广播时调用 requestPermission()
。 调用requestPermission()
显示一个对话框 用户请求允许连接到设备。 下面的示例代码显示了如何 创建广播接收机:
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { 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 (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ //call method to set up device communication } } else { Log.d(TAG, "permission denied for device " + device); } } } } };
注册广播接收器,添加你 onCreate()
方法在你的 活动:
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; ... mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter);
显示对话框,询问用户允许连接到设备,调用 requestPermission()
方法:
UsbDevice device; ... mUsbManager.requestPermission(device, mPermissionIntent);
当用户回复的对话框,你的广播接收器接收包含意图 EXTRA_PERMISSION_GRANTED
额外的,这是一个布尔值 代表回答。 之前检查这个额外的价值真正的连接 设备。
沟通与USB设备可以是同步或异步的。 在这两种情况下,你 应该创建一个新线程来执行所有数据传输,所以你不阻止 UI线程。 正确设置通信设备,你需要获得适当的 UsbInterface
和 UsbEndpoint
的 设备你想交流和发送在这个端点的请求 UsbDeviceConnection
。 一般来说,您的代码应该:
UsbDevice
对象的属性,如产品ID、 供应商ID,或者设备类找出你是否想与交流 设备。UsbInterface
您想使用与交流 适当的 UsbEndpoint
的接口。 接口可以有一个 或多个端点,通常会有一个双向的输入和输出端点 沟通。UsbDeviceConnection
端点。bulkTransfer()
或 controlTransfer()
方法。 你应该 在另一个线程执行这一步,防止阻塞主UI线程。 更多的 在Android使用线程的信息,明白了 流程和 线程 。下面的代码片段是一个微不足道的方式同步数据传输。 你的代码 应该有更多的逻辑来正确地找到正确的接口和通信端点 也应该做任何传输的数据比主UI线程在一个不同的线程:
private Byte[] bytes; private static int TIMEOUT = 0; private boolean forceClaim = true; ... UsbInterface intf = device.getInterface(0); UsbEndpoint endpoint = intf.getEndpoint(0); UsbDeviceConnection connection = mUsbManager.openDevice(device); connection.claimInterface(intf, forceClaim); connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread
异步发送数据,使用 UsbRequest
类 初始化
和 队列
一个异步请求,然后等待结果 与 requestWait()
。
有关更多信息,请参见 AdbTest样本 ,它显示了如何去做 异步批量转移, MissileLauncher样本 ,这 异步显示了如何监听一个中断端点。
当你完成与设备或通信如果分离设备,关闭 UsbInterface
和 UsbDeviceConnection
通过 调用releaseInterface()
和 close()
。 监听分离的事件, 创建一个广播接收器像下图:
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (device != null) { // call your method that cleans up and closes communication with the device } } } };
创建应用程序内的广播接收器,而不是清单,允许你 它运行时应用程序只处理分离事件。 这种方式,分离事件 只发送给当前正在运行的应用程序,而不是广播给所有的应用程序。