[Android]USB开发

声明:主要参照文档:
Android开发之USB数据通信
安卓USB通信之权限管理

第一:请求权限和请求权限回调(通过广播回调)

注册一个广播接收器用于接收USB权限被同意或拒绝后发出的广播

 //注册USB设备权限管理广播
         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); //ACTION_USB_PERMISSION为自定义的字符串
         context.registerReceiver(usbReceiver, filter);

其中usbReceiver的实现是:

private  BroadcastReceiver usbReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if(action.equals(ACTION_USB_PERMISSION)){//ACTION_USB_PERMISSION是前面我们自己自定义的字符串
                UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {
                        LogUtils.i("已获取USB权限");
                    }
                } else {
                    LogUtils.i("USB权限被拒绝");
                }
                   
    };

请求权限:

PendingIntent  mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);//关于这个mPermissionIntent ,具体的作用我还没弄明白,明白以后补充
manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
manager.requestPermission(device,mPermissionIntent);//device是具体某个usb设备

执行完这个后,界面会弹出对话框询问用户是否授予权限,然后会发送权限广播,所以上面我们注册一个广播接收器来判断权限状态

第二:注册USB设备插拔广播

USB设备被插/拔后同样会发送一个广播,因此我们需要注册一个接收器来接收这个广播

        IntentFilter stateFilter = new IntentFilter();
        stateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        stateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        context.registerReceiver(usbStateReceiver, stateFilter);

其中.usbStateReceiver的实现如下:

private  BroadcastReceiver usbStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //USB连接上手机时会发送广播android.hardware.usb.action.USB_STATE"及UsbManager.ACTION_USB_DEVICE_ATTACHED
            if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                LogUtils.i("有USB设备连接");
              
            
            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {//USB被拔出
                LogUtils.i("USB连接断开,程序退出!");
              
            }
        }
    };

详细介绍以上两种,另附一个自己写的USBUtil,里面的思路是,初始化话时传入要连接设备的VendorId和ProductId,然后自动进行搜索,连接,授权等。只暴露读/写,开/关给外界,其他的全部自己处理

未经测试,请勿直接使用,仅供参考!!!!

package com.police.policefaceproject.utils;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;

import java.util.Iterator;
import java.util.Map;

/**
 * Created by Administrator on 2018/4/18.
 */

public class USBUtils {
    private  Activity activity;
    private  final String ACTION_USB_PERMISSION = "com.gudi.usb.permission";
    private  UsbManager manager;
    private  PendingIntent mPermissionIntent;
    private  BroadcastReceiver usbReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if(action.equals(ACTION_USB_PERMISSION)){
                UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {
                        USBCtrl(context);
                    }
                } else {
                    LogUtils.i("USB权限被拒绝");
                    if(activity!=null && !activity.isDestroyed()){
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                UiUtils.Alert(activity, "权限错误", "请重新插拔设备后,授予应用访问USB权限","确定", new UiUtils.AlertCallBackOne() {

                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {

                                    }
                                });
                               ;
                            }
                        });
                    }

                }
            }
        }
    };
    private  UsbDeviceConnection usbConnection;
    private  UsbEndpoint uepIn;
    private  UsbEndpoint uepOut;
    private  int mProductId,mVendorId;
    private  BroadcastReceiver usbStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //USB连接上手机时会发送广播android.hardware.usb.action.USB_STATE"及UsbManager.ACTION_USB_DEVICE_ATTACHED
            if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {//判断其中一个就可以了
                LogUtils.i("有USB设备连接");
                showMsg("有USB设备连接");
                USBCtrl(context);
            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {//USB被拔出
                LogUtils.i("USB连接断开,程序退出!");
                showMsg("USB连接断开,请重试");
                closeConn();
            }
        }
    };

    public  void init(Activity context,int productId,int vendorId){
        activity = context;
        mProductId = productId;
        mVendorId = vendorId;
        manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
         //注册USB设备权限管理广播
         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
         context.registerReceiver(usbReceiver, filter);
        //注册USB设备插拔广播
        IntentFilter stateFilter = new IntentFilter();
        stateFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
        stateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        stateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        context.registerReceiver(usbStateReceiver, stateFilter);
     }

    private  Map<String,UsbDevice> getDevices(){
         if(manager != null){
             Map<String,UsbDevice> deviceMap = manager.getDeviceList();
             return  deviceMap;
         }

         return null;

     }

    private  UsbDeviceConnection openDevice(Context context,UsbDevice device){
        if(manager.hasPermission(device)){
            UsbDeviceConnection  DeviceConnection = manager.openDevice(device);
            return DeviceConnection;
        }else{
            LogUtils.i("请求USB权限");
            manager.requestPermission(device,mPermissionIntent);
            return null;
        }

    }

    private  void USBCtrl(Context context){
        //获取设备列表
        Map<String,UsbDevice> devicesList= getDevices();
        if(devicesList == null || devicesList.size() <=0){
            LogUtils.e("未查找到USB设备");
            showMsg("未查找到设备,请重新插拔设备");

        }else{
            //遍历寻找指定设备
            Iterator<UsbDevice> deviceIterator = devicesList.values().iterator();
            while(deviceIterator.hasNext()){
                UsbDevice usb= deviceIterator.next();
                if(usb.getVendorId() == mVendorId && usb.getProductId() == mProductId){
                    //查找到指定设备
                    connDevice(context,usb);
                    break;
                }
            }

        }
    }

    private  void connDevice(Context context,UsbDevice device){
        UsbEndpoint uep;

        //获得设备接口
        UsbInterface usbInterface = device.getInterface(0);
        //查找输入,输出端
        for(int i =0;i<usbInterface.getEndpointCount();i++){
            uep=usbInterface.getEndpoint(i);
            if(uep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK){
                if(uep.getDirection() == UsbConstants.USB_DIR_IN){
                    uepIn = uep;
                }else if(uep.getDirection() == UsbConstants.USB_DIR_OUT){
                    uepOut = uep;
                }
            }
        }
        usbConnection = openDevice(context,device);
        if(usbConnection == null){
            LogUtils.e("连接设备失败");
            showMsg("连接设备失败,请赋予权限");
            return ;
        }
        if(usbConnection.claimInterface(usbInterface,true)){//声明独占此接口,在发送或接收数据前完成
            //锁定成功

        }else{
            //锁定失败
            usbConnection.close();
            usbConnection = null;
            LogUtils.e("锁定接口失败");
            showMsg("锁定接口失败,请插拔设备重试");
        }

    }

    public   int  write(byte[] data){
        if(usbConnection != null){
           int len= usbConnection.bulkTransfer(uepOut, data, data.length, 3000);
            LogUtils.i("通过USB接口发送"+data.length+"数据");
            return len;
        }else{
            LogUtils.i("usbConnection为null");
            return -1;
        }
    }

    public  byte[] read(byte[] data){
        if(usbConnection != null){
            int len= usbConnection.bulkTransfer(uepOut, data, data.length, 3000);
            LogUtils.i("通过USB接口接收"+data.length+"数据");
            return data;
        }else{
            LogUtils.i("接收数据,usbConnection为null");
            return null;
        }
    }

    public  void closeConn(){
        if(usbConnection != null){
            usbConnection.close();
            usbConnection=null;
        }
    }
    private  void showMsg(final String msg){

        if(activity!=null ){
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    UiUtils.toast(activity.getApplicationContext(),msg);
                }
            });
        }
    }




}

未经测试,请勿直接使用,仅供参考!!!!

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

推荐阅读更多精彩内容

  • Android通过两种模式支持各种USB设备: USB accessory 和USB host。(Android ...
    wangdy12阅读 9,260评论 1 6
  • 一、先大致了解下Android里关于USB的API,下图很清晰的表示了Android里面USB的树状(图随便画的表...
    CrazyYong阅读 5,349评论 0 4
  • 项目中有一个新的需求,要求可以连接一个USB体温枪,APP可以从体温枪中读取到体温数据,一番搜寻之后发现一个封装很...
    junerver阅读 11,593评论 18 29
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 你,此时此刻,正在看手机...... 你有认真的算过吗?除了打电话,你每天泡在手机上的时间有多长? 你是不是总低头...
    马大哈哈镜花缘阅读 1,080评论 5 4