Android USB 开发

Android通过两种模式支持各种USB设备: USB accessory 和USB host。(Android 3.1 API 12 以上)

对USB主机和附件模式的支持最终取决于设备的硬件,和API级别无关。可以通过<uses-feature>元素过滤支持USB主机和附件的设备。

在这种情况下,因为USB接口被占用,使用WiFi调试

$ adb connect device_ip_address(电脑开WiFi,手机连接的IP)

USB Host Mode主机模式
Android设备充当主主设备,并为总线供电。
例如数字相机,键盘,鼠标和游戏控制器。USB设备与Android应用进行数据交互。

USB Accessory Mode附件模式
外部硬件充当USB主设备,并为总线供电。例如手机和电脑连接

USB Host and Accessory Modes

USB Host 端是主设备,Device是从设备


Host模式

此时Android设备作为主设备,对外供电,可以列出连接上的USB设备

相关API

android.hardware.usb包,提供了相关的支持

UsbManager
枚举设备、和所连接的USB设备通信

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

UsbDevice
代表一个连接的USB从设备,并包含访问其标识信息,接口和端点的方法。

UsbInterface
表示一个UsbDevice的一个接口。UsbDevice可以具有一个或多个在接口用来通信。

UsbEndpoint
表示一个UsbInterface一个端点,它是接口的通信通道。一个接口可以具有一个或多个端点,与设备进行双向通信通常有一个端点用于输入和一个端点用于输出。

UsbDeviceConnection
表示与设备的连接,用来收发数据,传输控制信息。

UsbRequest
通过UsbDeviceConnection与设备通信的异步请求,只用来异步通信

UsbConstants
USB常量定义,与Linux内核的linux / usb / ch9.h中的定义相对应

  1. UsbManager来检索所需的UsbDevice,找到对应的设备
  2. 找到合适的UsbInterfaceUsbEndpoint进行通信
  3. 获得正确的端点后,打开UsbDeviceConnection与USB设备进行通信。

在Manifest中声明需要的USB设备信息

这样,当检测到相应的USB设备插入的时候,系统会出现一个弹框,如果用户点击同意接入的话,可以直接启动应用相应的Activity

  • 声明需要的硬件功能
  • 设定最低API Level 12 (基本不需要了)
  • 在插入相关USB设备时通知应用程序,在相应Activity中为android.hardware.usb.action.USB_DEVICE_ATTACHEDIntent指定一个<intent-filter>和<meta-data>元素对。 <meta-data>元素指向一个外部XML资源文件(位于 res/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>

在XML资源文件中,通过<usb-device>元素声明要过滤的USB设备。
一般来说,使用供应商vendor-id和产品IDproduct-id过滤特定设备。
使用类class, 子类subclass, 和协议protocol 过滤一组设备
没有属性时,匹配每个USB设备

<usb-device>的属性如下

vendor-id
product-id
class
subclass
protocol (device or interface)

例如:声明过滤UVC摄像头
<usb-device class="239" subclass="2" />

使用设备

  • 发现连接的USB设备,通过使用<intent-filter>来获取通知,或者程序主动查询已经连接的设备,看是否感兴趣
  • 请求连接USB设备的权限(如果尚未获得)
  • 通过在相应的接口 endPoint上读取和写入数据与USB设备进行通信

发现一个设备

一种方法是在清单文件中指定一个<intent-filter>和<meta-data>元素对
当用户连接与设备过滤器匹配的设备时,系统会显示一个对话框,询问是否要启动程序,如果用户接受,应用程序自动有权访问设备,直到设备断开连接。

通过Intent获取代表接入设备的UsbDevice:

Intent intent = getIntent();
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

自动授予权限,此时intent的extra没有EXTRA_PERMISSION_GRANTED字段对应的boolen信息,只有EXTRA_DEVICE 字段对应的device信息

枚举设备
通过枚举总线上的设备,检查当前连接的所有USB设备。
HashMap 的Key值对应的是USB设备的名称

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

UsbDevice device = deviceList.get("deviceName");
//或者通过迭代的方式,对每个Device执行操作  
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
    UsbDevice device = deviceIterator.next();
    //your code
}

获取权限

在尝试与USB设备通信之前,必须检查访问设备的权限。 如果没有权限,会返回运行时错误。

如果使用Intent Filter来连接USB设备,插入设备,就会有系统弹框,点允许我们的应用处理此设备时,就会获得权限。如有点击方框,永久授予权限,一插入设备,就会自动启动应用对应的Activity。否则,必须在连接到设备之前明确请求许可。

当通过枚举查找已连接的USB设备,然后要与其通信时,需要显示请求许可,需要创建广播接收器,因为调用'requestPermission'请求权限时,返回信息包含在PendingIntent内部,Intent包含两个额外信息
EXTRA_DEVICE :表示调用请求时对应的设备
EXTRA_PERMISSION_GRANTED一个布尔值,表示是否授予权限

if (mUsbManager.hasPermission(device)) {
    //进行通信相关的操作
} else {
    mUsbManager.requestPermission(device, mPermissionIntent);
}

//函数原型
UsbManager.hasPermission(UsbDevice device)
UsbManager.requestPermission(UsbDevice device, PendingIntent mPermissionIntent)

注册广播,接收相应的请求权限后系统产生的广播Intent

private static final String ACTION_USB_PERMISSION =
    "com.android.example.USB_PERMISSION";
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
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){
                    //进行通信相关的操作
                   }
                }
                else {
                    Log.d(TAG, "permission denied for device " + device);
                }
            }
        }
    }
};

通信

通信肯定是要放到另一个线程中去操作,以免阻塞UI线程

//打开设备
UsbDeviceConnection connection = mUsbManager.openDevice(device);

[TODO]


参考

USB Host 官方资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容