[Android]USB開(kāi)發(fā)

聲明:主要參照文檔:
Android開(kāi)發(fā)之USB數(shù)據(jù)通信
安卓USB通信之權(quán)限管理

第一:請(qǐng)求權(quán)限和請(qǐng)求權(quán)限回調(diào)(通過(guò)廣播回調(diào))

注冊(cè)一個(gè)廣播接收器用于接收USB權(quán)限被同意或拒絕后發(fā)出的廣播

 //注冊(cè)USB設(shè)備權(quán)限管理廣播
         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); //ACTION_USB_PERMISSION為自定義的字符串
         context.registerReceiver(usbReceiver, filter);

其中usbReceiver的實(shí)現(xiàn)是:

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權(quán)限");
                    }
                } else {
                    LogUtils.i("USB權(quán)限被拒絕");
                }
                   
    };

請(qǐng)求權(quán)限:

PendingIntent  mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);//關(guān)于這個(gè)mPermissionIntent 帝际,具體的作用我還沒(méi)弄明白泌神,明白以后補(bǔ)充
manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
manager.requestPermission(device,mPermissionIntent);//device是具體某個(gè)usb設(shè)備

執(zhí)行完這個(gè)后径玖,界面會(huì)彈出對(duì)話框詢問(wèn)用戶是否授予權(quán)限卷雕,然后會(huì)發(fā)送權(quán)限廣播尚揣,所以上面我們注冊(cè)一個(gè)廣播接收器來(lái)判斷權(quán)限狀態(tài)

第二:注冊(cè)USB設(shè)備插拔廣播

USB設(shè)備被插/拔后同樣會(huì)發(fā)送一個(gè)廣播显押,因此我們需要注冊(cè)一個(gè)接收器來(lái)接收這個(gè)廣播

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

其中.usbStateReceiver的實(shí)現(xiàn)如下:

private  BroadcastReceiver usbStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //USB連接上手機(jī)時(shí)會(huì)發(fā)送廣播android.hardware.usb.action.USB_STATE"及UsbManager.ACTION_USB_DEVICE_ATTACHED
            if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                LogUtils.i("有USB設(shè)備連接");
              
            
            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {//USB被拔出
                LogUtils.i("USB連接斷開(kāi)扁达,程序退出走敌!");
              
            }
        }
    };

詳細(xì)介紹以上兩種匀借,另附一個(gè)自己寫的USBUtil颜阐,里面的思路是,初始化話時(shí)傳入要連接設(shè)備的VendorId和ProductId吓肋,然后自動(dòng)進(jìn)行搜索凳怨,連接,授權(quán)等。只暴露讀/寫肤舞,開(kāi)/關(guān)給外界紫新,其他的全部自己處理

未經(jīng)測(cè)試,請(qǐng)勿直接使用李剖,僅供參考C⒙省!8菟场偶芍!

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權(quán)限被拒絕");
                    if(activity!=null && !activity.isDestroyed()){
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                UiUtils.Alert(activity, "權(quán)限錯(cuò)誤", "請(qǐng)重新插拔設(shè)備后,授予應(yīng)用訪問(wèn)USB權(quán)限","確定", 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連接上手機(jī)時(shí)會(huì)發(fā)送廣播android.hardware.usb.action.USB_STATE"及UsbManager.ACTION_USB_DEVICE_ATTACHED
            if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {//判斷其中一個(gè)就可以了
                LogUtils.i("有USB設(shè)備連接");
                showMsg("有USB設(shè)備連接");
                USBCtrl(context);
            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {//USB被拔出
                LogUtils.i("USB連接斷開(kāi)德玫,程序退出匪蟀!");
                showMsg("USB連接斷開(kāi),請(qǐng)重試");
                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);
         //注冊(cè)USB設(shè)備權(quán)限管理廣播
         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
         context.registerReceiver(usbReceiver, filter);
        //注冊(cè)USB設(shè)備插拔廣播
        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("請(qǐng)求USB權(quán)限");
            manager.requestPermission(device,mPermissionIntent);
            return null;
        }

    }

    private  void USBCtrl(Context context){
        //獲取設(shè)備列表
        Map<String,UsbDevice> devicesList= getDevices();
        if(devicesList == null || devicesList.size() <=0){
            LogUtils.e("未查找到USB設(shè)備");
            showMsg("未查找到設(shè)備宰僧,請(qǐng)重新插拔設(shè)備");

        }else{
            //遍歷尋找指定設(shè)備
            Iterator<UsbDevice> deviceIterator = devicesList.values().iterator();
            while(deviceIterator.hasNext()){
                UsbDevice usb= deviceIterator.next();
                if(usb.getVendorId() == mVendorId && usb.getProductId() == mProductId){
                    //查找到指定設(shè)備
                    connDevice(context,usb);
                    break;
                }
            }

        }
    }

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

        //獲得設(shè)備接口
        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("連接設(shè)備失敗");
            showMsg("連接設(shè)備失敗,請(qǐng)賦予權(quán)限");
            return ;
        }
        if(usbConnection.claimInterface(usbInterface,true)){//聲明獨(dú)占此接口琴儿,在發(fā)送或接收數(shù)據(jù)前完成
            //鎖定成功

        }else{
            //鎖定失敗
            usbConnection.close();
            usbConnection = null;
            LogUtils.e("鎖定接口失敗");
            showMsg("鎖定接口失敗段化,請(qǐng)插拔設(shè)備重試");
        }

    }

    public   int  write(byte[] data){
        if(usbConnection != null){
           int len= usbConnection.bulkTransfer(uepOut, data, data.length, 3000);
            LogUtils.i("通過(guò)USB接口發(fā)送"+data.length+"數(shù)據(jù)");
            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("通過(guò)USB接口接收"+data.length+"數(shù)據(jù)");
            return data;
        }else{
            LogUtils.i("接收數(shù)據(jù),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);
                }
            });
        }
    }




}

未經(jīng)測(cè)試造成,請(qǐng)勿直接使用穗泵,僅供參考!C瞻獭5柩印!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夷磕,一起剝皮案震驚了整個(gè)濱河市履肃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坐桩,老刑警劉巖尺棋,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绵跷,居然都是意外死亡膘螟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門碾局,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荆残,“玉大人,你說(shuō)我怎么就攤上這事净当∧谒梗” “怎么了蕴潦?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俘闯。 經(jīng)常有香客問(wèn)我潭苞,道長(zhǎng),這世上最難降的妖魔是什么真朗? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任此疹,我火速辦了婚禮,結(jié)果婚禮上遮婶,老公的妹妹穿的比我還像新娘蝗碎。我一直安慰自己,他們只是感情好蹭睡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布衍菱。 她就那樣靜靜地躺著赶么,像睡著了一般肩豁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辫呻,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天清钥,我揣著相機(jī)與錄音,去河邊找鬼放闺。 笑死祟昭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的怖侦。 我是一名探鬼主播篡悟,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼匾寝!你這毒婦竟也來(lái)了搬葬?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤艳悔,失蹤者是張志新(化名)和其女友劉穎急凰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體猜年,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抡锈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乔外。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片床三。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杨幼,靈堂內(nèi)的尸體忽然破棺而出勿璃,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布补疑,位于F島的核電站歧沪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏莲组。R本人自食惡果不足惜诊胞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锹杈。 院中可真熱鬧撵孤,春花似錦、人聲如沸竭望。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咬清。三九已至闭专,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旧烧,已是汗流浹背影钉。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掘剪,地道東北人平委。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像夺谁,于是被迫代替她去往敵國(guó)和親廉赔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android通過(guò)兩種模式支持各種USB設(shè)備: USB accessory 和USB host匾鸥。(Android ...
    wangdy12閱讀 9,522評(píng)論 1 6
  • 一蜡塌、先大致了解下Android里關(guān)于USB的API,下圖很清晰的表示了Android里面USB的樹(shù)狀(圖隨便畫的表...
    CrazyYong閱讀 5,448評(píng)論 0 4
  • 項(xiàng)目中有一個(gè)新的需求扫腺,要求可以連接一個(gè)USB體溫槍岗照,APP可以從體溫槍中讀取到體溫?cái)?shù)據(jù),一番搜尋之后發(fā)現(xiàn)一個(gè)封裝很...
    junerver閱讀 11,673評(píng)論 18 29
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,138評(píng)論 25 707
  • 你笆环,此時(shí)此刻攒至,正在看手機(jī)...... 你有認(rèn)真的算過(guò)嗎?除了打電話躁劣,你每天泡在手機(jī)上的時(shí)間有多長(zhǎng)迫吐? 你是不是總低頭...
    馬大哈哈鏡花緣閱讀 1,143評(píng)論 5 4