Google官方usb开发教程理解

一.概念

Android 开放配件 (AOA) 支持功能可让外部 USB 硬件(Android USB 配件)与处于配件模式下的 Android 设备进行交互。当某台 Android 设备处于配件模式时,所连接的配件会充当 USB 主机(为总线供电并列举设备),而 Android 设备则充当 USB 配件。

AOA 有两个支持不同通信类型的版本:

  • AOAv1。支持通用配件通信和 adb 调试。适用于 Android 3.1(API 级别 12)及更高版本,在 Android 2.3.4(API 级别10)及更高版本中通过插件库获得支持。
  • AOAv2。支持音频流式传输和人机接口设备 (HID) 功能。适用于 Android 4.1(API 级别 16)。

如果使用通用配件协议(而不是使用 adb 或音频协议)与配件通信,则必须提供可以检测 USB 配件连接并建立通信的 Android 应用。

二.android usb通信模式

Android通过两种模式,来支持各种USB外围设备和Android USB附件(硬件实现了Android的附件协议):USB附件模式(accessory)和USB主机模式(host)。在USB附件模式下,外部 USB 硬件充当USB主机。Android设备作为附件的例子,包括机器人控制器、扩展插座(docking stations)、诊断和音乐设备、电子报亭(kiosks)、读卡器等其他设备。这种模式给予不具备主机功能的Android设备,与USB硬件通信的能力。Android USB附件,必须被设计为与装有Android的设备一起工作,并且必须遵循Android附件通讯协议。在USB主机模式下,装有Android的设备扮演着主机的角色。Android设备充当主机的例子,包括数码像机,键盘,鼠标和游戏控制器。那些适应面很广的USB设备,仍可以与Android应用交互,前提是这些Android应用可以正确的与这些设备通讯。

图1展示了两种模式的异同。当Android设备处于主机模式时,它扮演USB主机角色并为总线供电。当Android设备处于附件模式时,被连接的USB硬件(在这种情况下是一个Android USB附件)扮演主机角色并给总线供电。


Google官方usb开发教程理解_第1张图片
图1. USB主从模式

三.相关API

1.两个相关的类

First Header Second Header
UsbManager 允许枚举已连接的USB设备并与其通信
UsbAccessory 是代表USB配件的类,该类提供了方法访问配件的信息

通过
UsbManager manager = UsbManager.getInstance(this);
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

UsbAccessory accessory = UsbManager.getAccessory(intent);
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
来获取这两个类的实例

2.Android manifest

声明
为主活动中的 android.hardware.usb.action.USB_ACCESSORY_ATTACHED意图指定元素对。元素指向外部XML资源文件,该文件声明有关要检测的附件的标识信息。
在XML资源文件中,声明要过滤的附件的元素。每个都可以具有以下属性:manufacturer,model,version,将资源文件保存在res / xml /目录中。资源文件名(不带.xml扩展名)必须与在元素中指定的名称相同。
示例:
AndroidManifest.xml


    
     
    
    ...
    
      
        
            ...
            
                
            
 
            
        
    

res/xml/accessory_filter.xml:



    

四.通信过程

1.监听usb设备attach

先注册监听usb设备attach的广播,然后通过

list = usbManager.getAccessoryList();
accessory = list[0];

拿到辅助设备UsbAccessory的对象

2.授权

注册监听授权的广播,可以和监听usb设备attach的receiver合并

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) {
                UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
 
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if(accessory != null){
                        //call method to set up accessory communication
                    }
                }
                else {
                    Log.d(TAG, "permission denied for accessory " + accessory);
                }
            }
        }
    }
};

在Activity onCreat()注册此receiver

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);

在检测到usb设备attach后请求权限

UsbAccessory accessory;
...
mUsbManager.requestPermission(accessory, mPermissionIntent);

3.通信

授权成功后可以通过文件描述符进行通信

UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
 
...
 
private void openAccessory() {
    Log.d(TAG, "openAccessory: " + accessory);
    mFileDescriptor = mUsbManager.openAccessory(mAccessory);
    if (mFileDescriptor != null) {
        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        mInputStream = new FileInputStream(fd);
        mOutputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null, this, "AccessoryThread");
        thread.start();
    }
}

4.设备退出后关闭fd,清理

BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
 
        if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
            UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
            if (accessory != null) {
                // call your method that cleans up and closes communication with the accessory
                mFileDescriptor.close()
                ...
            }
        }
    }
};

五.参考

http://scottmaxiao.github.io/AOA.html

https://source.android.com/devices/accessories/protocol

官方文档https://developer.android.com/guide/topics/connectivity/usb/accessory

https://source.android.com/devices/accessories/custom

https://blog.csdn.net/gaojinshan/article/details/12012363

https://blog.csdn.net/yingzhao80/article/details/45511351

你可能感兴趣的:(Google官方usb开发教程理解)