1.Android通过两种模式支持各种USB设备

   USB host 和USB accessory   (Android3.1   API 12以上)

  USB Host Mode 主机模式:Android设备充当主设备,并为总线供电

  USB Accessory Mode  附件模式:外部硬件充当USB主设备,本机为附件

2.Android sdk中与usb相关的API

   UsbManager

   获取连接的USB设备并与之通信

   UsbManager.ACTION_USB_ACCESSORY_ATTACHED 设备插入

   UsbManager.ACTION_USB_ACCESSORY_DETACHED 设备拔出

   UsbDevice

   代表一个连接的USB 设备,包含一系列方法获取自身信息,包括interfaces,endpoints

  UsbInterface

  代表USB 设备上定义的一系列功能接口,一个usb设备可以有一个或多个接口

  UsbEndpoint

  代表一个interface通信频道,一个interface可以有一个或多个endpoints,一般含有输入输出两个端点来支持双工通信

   UsbDeviceConnection

   代表设备连接的一个链路,将数据传输到端点上,这个类允许你同步或异步的来回发送数据

   UsbRequest

   代表一个异步请求,通过UsbDeviceConnection来跟设备通信

   UsbConstants

   定义了linux内核文件linux/usb/ch9.h中的常量

3.android Host与accessory模式之间是通过AOA协议进行通讯

   所有的通道均在USB端点0进行
          3.1配件发送序号51的USB请求报文,手机收到后查询自己的AOA版本协议,发送响应报文给配件
          3.2配件校验协议版本号,目前为1或2,其他的均为不支持
          3.2配件发送序号52的USB请求报文,通过Index字段携带配件自身信息,包括制造商、型号、版本、设备描述、序 列号URI等。手机根据这些信息启动响应的APP
          3.4配件发送序号53的USB请求报文,切换USB模式,主要是根据切换的vendorID和productID
          3.5重新枚举USB设备,准备建立AOA数据通道

4.Android  Host模式相关代码

4.1 AndroidManifest文件设置(一定要加)

uses-feature 声明这个软件需要使用USB功能,申明这个Google Play会把不满足的设备过滤掉

usb对api级别有要求,必须是12或者更高,目前市面上的api都已达标这里不做过多处理

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

 

  4.1 android中关于usb连接的成功与失败,是通过系统广播的方式来获取的

        这里需要自定义两个广播来监听usb设备的连接与断开

/** * 用来监听系统下发的usb设备连接成功的广播 */public class OpenDevicesReceiver extends BroadcastReceiver {    private OpenDevicesListener mOpenDevicesListener;//usb设备连接的回调接口    public OpenDevicesReceiver(OpenDevicesListener openDevicesListener) {        mOpenDevicesListener = openDevicesListener;    }    private CommunicationListener listener;//sdk中用户打开usb连接成功的回调    public void setCommunicationListener(CommunicationListener listener) {//设置usb设备连接成功的回调        this.listener = listener;    }    @Override    public void onReceive(Context context, Intent intent) {        UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);//获取附件设备        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {//判断设备是都有usb            if (usbDevice != null) {                mOpenDevicesListener.openAccessoryModel(usbDevice);                listener.onSuccess(CommunicationCode.USB_OPEN_SUCCESS,"USB权限开启成功");                Toast.makeText(context, "USB权限开启成功", Toast.LENGTH_SHORT).show();            } else {                mOpenDevicesListener.openDevicesError();                listener.onFaild("USB设备连接异常");            }        } else {            //打开权限失败            mOpenDevicesListener.openDevicesError();            listener.onFaild("用户未授权USB权限");        }    }    public interface OpenDevicesListener {        /**         * 打开Accessory模式         *         * @param usbDevice         */        void openAccessoryModel(UsbDevice usbDevice);        /**         * 打开设备(手机)失败         */        void openDevicesError();    }}
/** * 用来监听系统下发的usb设备断开连接的广播 */public class UsbDetachedReceiver extends BroadcastReceiver {    private UsbDetachedListener mUsbDetachedListener; //usb连接断开的回调    /**     * 构造方法中添加回调参数     * @param usbDetachedListener     */    public UsbDetachedReceiver(UsbDetachedListener usbDetachedListener) {        mUsbDetachedListener = usbDetachedListener;    }    @Override    public void onReceive(Context context, Intent intent) {        mUsbDetachedListener.usbDetached();    }    public interface UsbDetachedListener {        /**         * usb断开连接         */        void usbDetached();    }}

4.2对应用户操控usb的四个状态: 开启usb 、关闭usb、发送数据、接收数据

     定义接口基类

public interface BaseCommunication {    /**     * 开启通讯接口     * @return 200 表示成功开启     */    public void openCommunication(CommunicationListener listener);    /**     * 关闭通讯接口     */    public void closeCommunication();    /**     * 发送byte[]类型数据     */    public void sendMessage(byte[] bytes, SendMessageListener listener);    /**     * 接收byte[]类型数据     */    public  void receiveMessage(ReciverMessageListener listener);}

4.3关于基类中的三个回调:开启usb成功的回调、发送数据成功的回调、接受数据成功的回调,关闭usb连接时只需要把相关的资源注销掉即可

/** * usb连接开启成功或失败的回调 */public interface CommunicationListener {    void onSuccess(int code, String msg);    void onFaild(String msg);}

 

/** * usb接受数据成功或失败的回调 */public interface ReciverMessageListener {    void onSuccess(byte[] bytes);    void onFaild(String msg);}

 

/** * usb发送数据成功或失败的回调 */public interface SendMessageListener {    void onSuccess();    void onFaild(String msg);}

4.4 编写基类实现UsbCommunication

public class UsbCommunication implements BaseCommunication, UsbDetachedReceiver.UsbDetachedListener, OpenDevicesReceiver.OpenDevicesListener {    //usb设备连接广播    private OpenDevicesReceiver mOpenDevicesReceiver;    //usb连接断开广播    private UsbDetachedReceiver mUsbDetachedReceiver;    //需要使用context初始化相关usb资源    private Context mContext;    //usb设备管理器    private UsbManager mUsbManager;    //自定义usb权限action    private static final String USB_ACTION = "com.wiseasy.communication.usb.hostchart";    /**     * Handler相关判断的变量,对应:usb连接初始化成功、失败,usb连接接收消息成功、失败,usb连接发送消息成功、失败     */    private static final int RECEIVER_MESSAGE_SUCCESS = 1;    private static final int SEND_MESSAGE_SUCCESS = 2;    private static final int RECEIVER_MESSAGE_FAILED = 3;    private static final int SEND_MESSAGE_FAILED = 4;    private static final int INIT_FAILED = 5;    private static final int INIT_SUCCESS = 6;    //接收消息监听回调    private ReciverMessageListener reciverMessageListener;    //接收消息监听回调    private SendMessageListener sendMessageListener;    /**     * 使用handler将所有的操作统一到主线程     */    @SuppressLint("HandlerLeak")    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case RECEIVER_MESSAGE_SUCCESS://成功接受到数据                    reciverMessageListener.onSuccess((byte[]) msg.obj);                    break;                case RECEIVER_MESSAGE_FAILED://接收消息失败                    reciverMessageListener.onFaild("接受消息失败");                    break;                case SEND_MESSAGE_SUCCESS://发送数据成功                    sendMessageListener.onSuccess();                    break;                case SEND_MESSAGE_FAILED://发送数据失败                    sendMessageListener.onFaild("发送消息失败");                    break;                case INIT_SUCCESS://usb主附设备连接陈工                    communicationListener.onSuccess(CommunicationCode.USB_OPEN_SUCCESS, "初始化成功");                    break;                case INIT_FAILED://usb主附设备连接失败                    communicationListener.onFaild("初始化失败");                    break;            }        }    };    /**     * 单例模式 初始化     *     * @param context     */    private UsbCommunication(Context context) {        /**         * 为了避免在单利模式下的内存泄露,这里将context统一转换为ApplicationContext         */        this.mContext = context.getApplicationContext();        //注册usb连接断开的广播        mUsbDetachedReceiver = new UsbDetachedReceiver(this);        IntentFilter intentFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);        mContext.registerReceiver(mUsbDetachedReceiver, intentFilter);        //通过context获取到当前系统的USB管理器        mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);    }    //单例变量    private static volatile UsbCommunication Instance;    /**     * 单利模式双重检查     *     * @param context     * @return     */    public static UsbCommunication getInstance(Context context) {        if (Instance == null) {            synchronized (UsbCommunication.class) {                if (Instance == null) {                    Instance = new UsbCommunication(context);                }            }        }        return Instance;    }    //usb连接开启成功或失败的回调    private CommunicationListener communicationListener;    /**     * 开启usb连接的接口实现     *     * @param communicationListener     */    @Override    public void openCommunication(CommunicationListener communicationListener) {        this.communicationListener = communicationListener;        //用来申请usb权限        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(USB_ACTION), 0);        //注册usb连接开启的广播        mOpenDevicesReceiver = new OpenDevicesReceiver(this);        IntentFilter intentFilter = new IntentFilter(USB_ACTION);        mContext.registerReceiver(mOpenDevicesReceiver, intentFilter);        //设置连接成功的监听回调        mOpenDevicesReceiver.setCommunicationListener(communicationListener);        /**         * 通过usbManager获取当前连接的设备集合         * 遍历集合通过productId过滤不符合条件的设备         */        HashMap deviceList = mUsbManager.getDeviceList();        if (deviceList != null) {            for (UsbDevice usbDevice : deviceList.values()) {                int productId = usbDevice.getProductId();                if (productId != 377 && productId != 7205) {                    if (mUsbManager.hasPermission(usbDevice)) {                        /**                         * 通过AOA协议让附件设备进入到accessory模式                         */                        initAccessory(usbDevice);                    } else {                        //申请usb权限                        mUsbManager.requestPermission(usbDevice, pendingIntent);                    }                }            }        } else {            //连接失败回调            communicationListener.onFaild("请连接USB");        }    }    /**     * AOA协议部分     *     * @param usbDevice     */    private void initAccessory(UsbDevice usbDevice) {        //获取usb连接通道        UsbDeviceConnection usbDeviceConnection = mUsbManager.openDevice(usbDevice);        if (usbDeviceConnection == null) {            communicationListener.onFaild("请连接USB");            return;        }        //根据AOA协议打开Accessory模式        initStringControlTransfer(usbDeviceConnection, 0, "Google, Inc."); // MANUFACTURER        initStringControlTransfer(usbDeviceConnection, 1, "AccessoryChat"); // MODEL        initStringControlTransfer(usbDeviceConnection, 2, "Accessory Chat"); // DESCRIPTION        initStringControlTransfer(usbDeviceConnection, 3, "1.0"); // VERSION        initStringControlTransfer(usbDeviceConnection, 4, "http://www.android.com"); // URI        initStringControlTransfer(usbDeviceConnection, 5, "0123456789"); // SERIAL        usbDeviceConnection.controlTransfer(0x40, 53, 0, 0, new byte[]{}, 0, 100);        usbDeviceConnection.close();        initDevice();//子设备初始化    }    private void initStringControlTransfer(UsbDeviceConnection deviceConnection, int index, String string) {        deviceConnection.controlTransfer(0x40, 52, 0, index, string.getBytes(), string.length(), 100);    }    //usb设备连接通道    private UsbDeviceConnection mUsbDeviceConnection;    //usb接口    private UsbInterface mUsbInterface;    //usb输出端点    private UsbEndpoint mUsbEndpointOut;    //usb输入端点    private UsbEndpoint mUsbEndpointIn;    private void initDevice() {        /**         * 使用usbManager遍历设备集合,通过productId找出匹配accessory模式的设备         */        HashMap deviceList = mUsbManager.getDeviceList();        Collection values = deviceList.values();        if (!values.isEmpty()) {            for (UsbDevice usbDevice : values) {                int productId = usbDevice.getProductId();                if (productId == 0x2D00 || productId == 0x2D01) {                    if (mUsbManager.hasPermission(usbDevice)) {                        //获取当前usb设备的通讯连接                        mUsbDeviceConnection = mUsbManager.openDevice(usbDevice);                        if (mUsbDeviceConnection != null) {                            //获取通讯连接接口                            mUsbInterface = usbDevice.getInterface(0);                            //获取通讯连接端点数量                            int endpointCount = mUsbInterface.getEndpointCount();                            for (int i = 0; i < endpointCount; i++) {                                //遍历所有端点,找到输入端点与输出端点                                UsbEndpoint usbEndpoint = mUsbInterface.getEndpoint(i);                                if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {                                    if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {                                        mUsbEndpointOut = usbEndpoint;//赋值输出端点                                    } else if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {                                        mUsbEndpointIn = usbEndpoint;//赋值输入端点                                    }                                }                            }                            //当输出端点和输入端点都不为空时,表示usb连接成功,初始化完成,可以进行数据收发                            if (mUsbEndpointOut != null && mUsbEndpointIn != null) {                                mHandler.sendEmptyMessage(INIT_SUCCESS);                            }                        }                    } else {                        //申请usb权限                        mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(USB_ACTION), 0));                    }                }            }        } else {            //初始化失败            mHandler.sendEmptyMessage(INIT_FAILED);        }    }    /**     * 关闭usb连接     * 释放所有资源     */    @Override    public void closeCommunication() {        if (mUsbDeviceConnection != null) {            mUsbDeviceConnection.releaseInterface(mUsbInterface);            mUsbDeviceConnection.close();            mUsbDeviceConnection = null;        }        mUsbEndpointIn = null;        mUsbEndpointOut = null;        isReceiverMessage = false;        mContext.unregisterReceiver(mUsbDetachedReceiver);        mContext.unregisterReceiver(mOpenDevicesReceiver);    }    /**     * 发送数据接口实现     * 发送byte[]类型数据     * 通过回调监听成功或失败     * @param bytes     * @param listener     */    @Override    public void sendMessage(final byte[] bytes, SendMessageListener listener) {        this.sendMessageListener = listener;        if (bytes != null) {            /**             * 耗时操作在子线程中执行             */            new Thread(new Runnable() {                @Override                public void run() {                    /**                     * 发送数据的地方 , 只接受byte数据类型的数据                     */                    int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, bytes, bytes.length, 3000);                    if (i > 0) {//大于0表示发送成功                        mHandler.sendEmptyMessage(SEND_MESSAGE_SUCCESS);                    } else {                        mHandler.sendEmptyMessage(SEND_MESSAGE_FAILED);                    }                }            }).start();        } else {            listener.onFaild("发送数据为null");        }    }    //接收数据循环变量,usb连接成功后需要一直监听用户发送的数据    private boolean isReceiverMessage = true;    //暂定的接收数据的大小,需要优化    private byte[] mBytes = new byte[1024];    /**     * 接收数据的实现     * 通过回调来返回接收的数据     * 使用handler来传递接收的数据到主线程     * @param listener     */    @Override    public void receiveMessage(final ReciverMessageListener listener) {        this.reciverMessageListener = listener;        new Thread(new Runnable() {            @Override            public void run() {                SystemClock.sleep(1000);                while (isReceiverMessage) {                    /**                     * 循环接受数据的地方 , 只接受byte数据类型的数据                     */                    if (mUsbDeviceConnection != null && mUsbEndpointIn != null) {                        int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, mBytes, mBytes.length, 3000);                        if (i > 0) {                            Message message = Message.obtain();                            message.what = RECEIVER_MESSAGE_SUCCESS;                            message.obj = mBytes;                            mHandler.sendMessage(message);                        }                    } else {                        mHandler.sendEmptyMessage(RECEIVER_MESSAGE_FAILED);                    }                }            }        }).start();    }    /**     * 主设备开启成功,进行从设备唤醒     *     * @param usbDevice     */    @Override    public void openAccessoryModel(UsbDevice usbDevice) {        initAccessory(usbDevice);    }    /**     * 主设备权限被拒绝     */    @Override    public void openDevicesError() {        Toast.makeText(mContext, "USB权限被拒绝", Toast.LENGTH_SHORT).show();    }    /**     * usb连接断开 释放资源     */    @Override    public void usbDetached() {        if (mUsbDeviceConnection != null) {            mUsbDeviceConnection.releaseInterface(mUsbInterface);            mUsbDeviceConnection.close();            mUsbDeviceConnection = null;        }        mUsbEndpointIn = null;        mUsbEndpointOut = null;//        mToggle = false;        isReceiverMessage = false;        mContext.unregisterReceiver(mUsbDetachedReceiver);        mContext.unregisterReceiver(mOpenDevicesReceiver);    }}

4.5 MainActivity中的实际调用方式

    

UsbCommunication usbCommunication  =  UsbCommunication.getInstance(this);//初始化usb连接对象
usbCommunication.openCommunication(new CommunicationListener() {//开启usb连接     @Override     public void onSuccess(int code, String msg) {//连接成功         sendMessage.setEnabled(true);         getUsbMessage();//接收usb数据     }     @Override     public void onFaild(String msg) {//连接失败         Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();     } });

 

//接收数据,需要在初始化完成以后
private void getUsbMessage() {    //接收数据    usbCommunication.receiveMessage(new ReciverMessageListener() {        @Override        public void onSuccess(byte[] bytes) {            usbMessage = new String(bytes);            log.setText(usbMessage);        }        @Override        public void onFaild(String msg) {            Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();        }    });}

发送数据

String msg = message.getText().toString().trim();if (TextUtils.isEmpty(msg)) {    Toast.makeText(MainActivity.this, "请输入要发送的信息", Toast.LENGTH_LONG).show();    return;}usbCommunication.sendMessage(msg.getBytes(), new SendMessageListener() {    @Override    public void onSuccess() {        Toast.makeText(MainActivity.this, "信息发送成功", Toast.LENGTH_SHORT).show();    }    @Override    public void onFaild(String msg) {        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();    }});

 

  //usb连接断开时会自动释放资源,也可以主动调用close方法释放资源,

@Overrideprotected void onDestroy() {    super.onDestroy();    UsbCommunication.getInstance(this).closeCommunication();}

更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. android adb通过wifi查看日志
  3. Eclipse在线安装ADT等Android插件连接不上的解决方案
  4. android下的读写权限
  5. Android开发经验谈之应用间数据共享
  6. [Android(安卓)SQLite]数据存储与访问 - 外部存储
  7. android 客户端数据传递之一:Web Service 代码
  8. 数据储存方式-SharedPreferences
  9. ConnectivityManager详解

随机推荐

  1. Android(安卓)Activity横屏、竖屏、全屏
  2. Android与Html5交互
  3. Android开发之杂记(2)
  4. 当EditText是多行文本时, 光标如何设置在
  5. 【适配】【转】Android开发:最全面、最易
  6. Android(安卓)基础:SharePreferences知识
  7. Android软键盘显示模式及打开和关闭方式(
  8. 简解selector的几个属性
  9. Android布局属性介绍
  10. Android在layout xml中使用include