Android Usb Host

一. Usb模式介绍

https://blog.csdn.net/Yoryky/article/details/81813717
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.1.0_r41
repo sync

1. Usb Host 主模式
USB Host,中文意思是USB主模式,是相对于USB Accessory(USB副模式)来说的。如果Android工作在USB Host模式下,则连接到Android上的USB设备把Android类似的看作是一台PC机,PC机能干的事儿,Android也能干,例如将鼠标、键盘插入则可以使用键盘、鼠标来操作Android系统,如果插入U盘则,通过Android可以读写U盘上的数据。
2. Accessory 副模式
USB Accessory模式表示将Android设备类似当作一个USB的键盘、鼠标、U盘插入到电脑主机上一样使用。

本文主要讲解Usb Host 主模式
在Android中,主要通过UsbManager类去实现其功能

UsbManager mUsbManager= (UsbManager)mContext.getSystemService(Context.USB_SERVICE);

二. 主要功能

2.1 查找设备。

 HashMap<String , UsbDevice> deviceList = mUsbManager.getDeviceList();
        if(deviceList!=null && deviceList.size()>0){
            Iterator<UsbDevice> deviceIter = deviceList.values().iterator();
            while(deviceIter.hasNext()){
                UsbDevice _device = deviceIter.next();
                //请求权限
                if(!mUsbManager.hasPermission(_device)){
                    mUsbManager.requestPermission(_device , mPermissionIntent);
                }
            }
        }else{
            //no device
        }

2.2 过滤设备。
通过供应商Id,与产品Id来过滤设备

 private boolean isSupportDevice(UsbDevice device,int vendorId, int pid){
          if(device.getVendorId()==vendorId && device.getProductId() == pid){
                return true;
            }else{
                return false;
            }
    }

2.2 注册广播,监听状态
一般Usb需要监听状态主要分为以下几种:

  • 插入usb USB_STATE_ATTACH
  • 拨出usb USB_STATE_DETACH
  • 系统弹出是否允许权限时,用户选择了不允许。USB_STATE_PERMISSION_DENIED

以下是检测usb状态方法类,及其使用方法代码:

package per.yue.android.blog.usbdemo;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;

import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by matth on 2018/7/13.
 */

public class UsbCheckUtil {
    public static final int USB_STATE_PERMISSION_DENIED=1;
    public static final int USB_STATE_ATTACH=2;
    public static final int USB_STATE_DETACH=3;
    public static final int USB_STATE_NO_DEVICE=4;

    //当verdorId=-1时,表示不过滤设备
    private int vendorId=-1;
    private int pId=-1;

    private OnUsbStateChange listener;

    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent= null;
    //任意字符串,一般以包名开头
    private static final String ACTION_USB_PERMISSION = "per.yue.android.blog.usbdemo.USB_PERMISSION";
    private Context mContext;

    public UsbCheckUtil(Context context,OnUsbStateChange l){
        mContext=context;
        vendorId=-1;
        pId=-1;
        listener=l;
    }
    public UsbCheckUtil(Context context,OnUsbStateChange l,int vendorId,int pId){
        mContext=context;
        this.vendorId=vendorId;
        this.pId=pId;
        listener=l;
    }


    //初始化
    public void init(){
        mUsbManager= (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
        mPermissionIntent = PendingIntent.getBroadcast(mContext,0,new Intent(ACTION_USB_PERMISSION),0);
        register();
        findUsbDevice();
    }

    /**
     * 遍历usb设备
     */
    private void findUsbDevice(){
        HashMap<String , UsbDevice> deviceList = mUsbManager.getDeviceList();
        if(deviceList!=null && deviceList.size()>0){
            Iterator<UsbDevice> deviceIter = deviceList.values().iterator();
            while(deviceIter.hasNext()){
                UsbDevice _device = deviceIter.next();
                boolean isSupport = isSupportDevice(_device.getVendorId(),_device.getProductId());
                if(!isSupport){
                    return;
                }
                if(!mUsbManager.hasPermission(_device)){
                    mUsbManager.requestPermission(_device , mPermissionIntent);
                }
            }
        }else{
            Log.i("vlog","no device");
            if(listener!=null){
               listener.stateChange(USB_STATE_NO_DEVICE,null);
            }
        }
    }


    /**
     * 释放资源
     */
    public void release(){
        mContext.unregisterReceiver(mUsbReceiver);
    }

    /**
     * 注册广播,监听usb的各种状态
     */
    private void register(){
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        //DEVICE_ATTACHED
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        //DEVICE_DETACHED
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        mContext.registerReceiver(mUsbReceiver, filter);
    }

    /**
     * 是不是支持的设备,通过vendorId过滤设备
     * @param _vendorId
     * @return
     */
    private boolean isSupportDevice(int _vendorId,int _pid){
        if(vendorId==-1){
            //不对设备作过滤
            return true;
        }else{
            if(vendorId==_vendorId && pId==_pid){
                return true;
            }else{
                return false;
            }
        }
    }

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver(){
        public void onReceive(Context context, Intent intent){

            UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            boolean isSupport = isSupportDevice(device.getVendorId(),device.getProductId());
            if(!isSupport){
                //不受支持的设备,不作任何处理
                return;
            }
            String action = intent.getAction();
            switch (action){
                case ACTION_USB_PERMISSION:
                    synchronized(this){
                        if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)){
                            Log.i("vlog","EXTRA_PERMISSION_GRANTED true");
                        }
                        else{
                            if(listener!=null){
                                listener.stateChange(USB_STATE_PERMISSION_DENIED,device);
                            }
                        }
                    }
                    break;
                case UsbManager.ACTION_USB_DEVICE_DETACHED:
                    if(listener!=null){
                        listener.stateChange(USB_STATE_DETACH,device);
                    }
                    break;
                case UsbManager.ACTION_USB_DEVICE_ATTACHED:
                    if(!mUsbManager.hasPermission(device)){
                        mUsbManager.requestPermission(device , mPermissionIntent);
                    }
                    if(listener!=null){
                        listener.stateChange(USB_STATE_ATTACH,device);
                    }
                    break;
            }


        }
    };

    public interface OnUsbStateChange{
        public void stateChange(int state,UsbDevice usbDevice);
    }

}


package per.yue.android.blog.usbdemo;
import android.hardware.usb.UsbDevice;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity{
    private TextView tv_msg;
    private UsbCheckUtil usbCheckUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_msg=(TextView) findViewById(R.id.tv_msg);

        usbCheckUtil=new UsbCheckUtil(MainActivity.this, new UsbCheckUtil.OnUsbStateChange() {
            @Override
            public void stateChange(int state, UsbDevice usbDevice) {
                StringBuilder stringBuilder=new StringBuilder();
                Log.i("vlog","state:"+state);

                switch (state){
                    case UsbCheckUtil.USB_STATE_ATTACH:
                        stringBuilder.append("USB_STATE_ATTACH\n");
                        break;
                    case UsbCheckUtil.USB_STATE_DETACH:
                        stringBuilder.append("USB_STATE_DETACH\n");
                        break;
                    case UsbCheckUtil.USB_STATE_PERMISSION_DENIED:
                        stringBuilder.append("USB_STATE_PERMISSION_DENIED\n");
                        break;
                    case UsbCheckUtil.USB_STATE_NO_DEVICE:
                        stringBuilder.append("USB_STATE_NO_DEVICE\n");
                        break;
                    default:
                        stringBuilder.append("No such state\n");
                        break;
                }

                if(usbDevice==null){
                    stringBuilder.append("Usb device is null\n");
                }else{
                    stringBuilder.append("VendorId:"+usbDevice.getVendorId()+"\n");
                    stringBuilder.append("ProductId:"+usbDevice.getProductId()+"\n");
                }
                Log.i("vlog","msg:"+stringBuilder.toString());
                showMsg(stringBuilder.toString());
            }
        },5841,1057);
        usbCheckUtil.init();
    }

    private void showMsg(String msg){
        tv_msg.setText(msg);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(usbCheckUtil!=null){
            usbCheckUtil.release();
        }
    }
}

三. 配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="per.yue.android.blog.usbdemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <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>

在MainActivity里配置以下代码:

    <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" />

实现的效果是当usb设备接入时,会弹出权限请求框,当用户点击ok时,此时会打开MainActivity

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

推荐阅读更多精彩内容

  • 接入前先了解一下USB OTG的概念 USB OTG:USB On-The-Go通常缩写为USB OTG,是USB...
    gstansen阅读 22,576评论 7 23
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,279评论 25 707
  • 微信里又有好友留言:要五斤鸡蛋,谢谢! 哦,得空马上给娘舅电话:娘舅,这周准备五斤鸡蛋,要新鲜的哦! 老程听了总是...
    果然Y阅读 546评论 4 2
  • 出现如下页面,点击红圆圈处 点击如下链接 https://petitions.whitehouse.gov/pet...
    YongFeng_7ec6阅读 272评论 0 0
  • 披着薄雾,在弥漫着风的寒里期盼阳光 光洒在大地上,活动开来 像一只猫,懒懒趴着 回头,路灯下的小女孩 只余细长的影
    零桶阅读 75评论 0 0