日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

usb附件连接方式

發(fā)布時(shí)間:2025/3/15 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 usb附件连接方式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android通過兩種模式來支持各種USB外設(shè)和Android USB配件(指那些符合Android附件協(xié)議的硬件):USB配件和USB主機(jī)。在USB配件的模式之下,外部的USB配件就像USB主機(jī)那樣。這種配件可以包括機(jī)器人控制器,基站連接器,醫(yī)療和音樂設(shè)備,電話亭以及讀卡器這樣很多的設(shè)備。這樣就使得那些搭載Android系統(tǒng)的設(shè)備不需要具備主機(jī)的特性就可以和USB硬件進(jìn)行交互。Android USB配件是指那些專門用來為搭載Android系統(tǒng)的設(shè)備工作以及符合Android附件通信協(xié)議的設(shè)備。在USB主機(jī)的模式之下,搭載Android的設(shè)備就像主機(jī)那樣工作。這些設(shè)備包括數(shù)碼相機(jī),鍵盤,鼠標(biāo)以及游戲控制器。Android USB設(shè)備被設(shè)計(jì)成具有廣泛的應(yīng)用領(lǐng)域,可以很好的完成人機(jī)互動應(yīng)用的通信設(shè)備。

1就顯示了這兩種模式的區(qū)別。當(dāng)搭載Android系統(tǒng)的設(shè)備處于主機(jī)的模式下,它就充當(dāng)USB主機(jī)并且為總線提供能源。而當(dāng)搭載Android系統(tǒng)的設(shè)備處于USB配件的模式下時(shí),連接的USB硬件(這種情況下,指的是一個(gè)Android USB配件)作為主機(jī)一樣并且為總線提供能源。

Android3.1API12級)或較新的平臺直接支持USB配件和主機(jī)模式。USB配件模式以一個(gè)附加的類庫的方式支持范圍更廣的設(shè)備 被移植到Android 2.3.4(API10)。設(shè)備生產(chǎn)商可以決定是否在系統(tǒng)鏡像上附加這個(gè)類庫。

注意:支持USB主機(jī)和配件模式主要取決于設(shè)備的硬件,而不是平臺的等級。你可以通過一個(gè)[[<uses-feature>]]元素來為設(shè)備進(jìn)行過濾以支持USB主機(jī)和配件。 看這個(gè)USB配件主機(jī)文檔來了解更多的詳情。

調(diào)試注意事項(xiàng)

當(dāng)用USB主機(jī)或者配件調(diào)試應(yīng)用程序時(shí),你最好有連接到搭載Android程序的設(shè)備的USB硬件。這樣可以避免你要通過USB來為搭載Android的設(shè)備建立一個(gè)adb的連接。你可以在一個(gè)網(wǎng)絡(luò)連接中一直連著adb。確保adb在一個(gè)網(wǎng)絡(luò)連接的方式:

1.通過USB連接搭載Android系統(tǒng)的設(shè)備和你的電腦

2.在命令提示符中找到你的SDK platform_tools/ 目錄,輸入 adb tcpip 5555

3.輸入 adb connect <device-ip-address>: 5555 你應(yīng)該已經(jīng)連接到了搭載Android程序的設(shè)備并且能夠發(fā)出像 adb logcat這樣一般 的adb命令

4.USB上為你的設(shè)備設(shè)置一個(gè)監(jiān)聽,輸入 adb usb

USB配件

USB配件模式允許用戶連接那些專門搭載Android設(shè)備的USB主機(jī)硬件。這些配件必須遵守Android配件開發(fā)工具包文檔中所列出的Android附件協(xié)議。這使得搭載Android系統(tǒng)的設(shè)備在不充當(dāng)USB主機(jī)的情況之下,仍然可以和USB硬件進(jìn)行交互。當(dāng)一臺搭載Android系統(tǒng)的設(shè)備處于USB配件模式時(shí),所依附的Android USB配件作為主機(jī)為USB總線提供能源以及列舉出相連的設(shè)備。Android3.1(API12)提供了USB配件模式并且這一特點(diǎn)也繼承了Android2.3.4(API10)以此來支持更多設(shè)備。

選擇正確的USB附件APIs

盡管USB附件APIAndroid3.1平臺才開始介紹,但是也可以在Android2.3.4API中通過附加類庫使用。因?yàn)檫@些APIs都是通過額外的類庫來使用的,你可以導(dǎo)入兩個(gè)包來支持USB配件模式。取決于你想支持什么樣的搭載Android系統(tǒng)的設(shè)備,你也許不得不在一個(gè)的基礎(chǔ)上使用另外一個(gè):

com.android.feature.usb:為了支持Android2.3.4USB配件模式,Google APIs附加類庫包括了USB外設(shè)APIs并且它們就是包含在這個(gè)命名空間的后面。Android3.1還支持導(dǎo)入和調(diào)用這個(gè)命名空間的類來支持附加類庫編寫的應(yīng)用程序。這個(gè)附加的類庫只是關(guān)于android.hardware.usb外設(shè)APIs的一個(gè)簡單的封裝并且它不支持USB主機(jī)模式。如果你希望更大范圍支持USB配件模式的設(shè)備,使用附加類庫并且導(dǎo)入改包就行。需要注意的是,并不是所有搭載Android2.3.4的設(shè)備都需要擁有USB外設(shè)這一特色。每個(gè)設(shè)備生產(chǎn)商在決定是否具有這個(gè)特色,這也就是為什么你必須要在manifest文件中聲明的原因了。

android.hardware.usb:這個(gè)命名空間包含在Android3.1版本中支持USB附件模式的類。因?yàn)檫@個(gè)包是框架APIs中的一部分,所以Android3.1版本可以在不用附加類庫的前提之下支持USB附件模式。使用這個(gè)包時(shí),如果你只關(guān)心Android3.1或者更新的支持USB附件模式的硬件的設(shè)備,你可以在mainfest文件中進(jìn)行聲明。

安裝谷歌APIs的附加類庫

如果你想安裝這個(gè)附加類庫,你可以通過在SDK管理器上面安裝谷歌APIs中的Android API10包的方式來做。更多關(guān)于安裝附加類庫的信息請參見安裝谷歌APIs附加元件

API 概述

因?yàn)楦郊宇悗焓且粋€(gè)框架APIs的封裝,和那些支持USB附件功能的類是相似的。即使你在用附加類庫的時(shí)候,你也可以用android.hardware.usb參考文檔作為參考。

注意:然而,你要注意在附加類庫和框架APIs之間還是有一些細(xì)微的使用差別的。

下面的表格為您描述了那些支持USB外設(shè)APIs的類:

詳細(xì)描述

UsbManager

允許您用已連接的USB配件直接進(jìn)行枚舉和交流

UsbAccessory

可以表示一個(gè)USB配件并且包含來連接識別信息的方法

關(guān)于平臺APIs和附加類庫之間的用法差異

在分別使用谷歌APIs附加類庫和平臺APIs的時(shí)候,通常會有兩種差異。

如果您正在使用附加類庫,則肯定會通過下列方式來創(chuàng)建UsbManager對象:

???UsbManager manager = UsbManager.getInstance(this);

如果您不是用的附加類,則必須通過下列方式來創(chuàng)建UsbManager對象:

???UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

當(dāng)您通過一個(gè)意圖過濾器來過濾一個(gè)已經(jīng)連接的配件,那么這個(gè)UsbAccessory對象就必須包含在傳給您應(yīng)用的這個(gè)意圖中。如果您正在使用附加類庫,您就必須通過下列方式來聲明UsbAccessory對象:

??UsbAccessory accessory = UsbManager.getAccessory(intent);

如果您不是用的附加類,則必須通過下列方式來聲明UsbAccessory對象:

?UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

Android ManiFest 需求

?

下面的列表向您描述了在用USB配件APIs工作前需要在您應(yīng)用中的manifest文件里面添加什么。下面的清單和資源文件例子將教您如何聲明這些項(xiàng):

  • 因?yàn)椴⒉皇撬写钶dAndroid系統(tǒng)的設(shè)備都保證支持USB配件APIs,包括一個(gè)<uses-feature>元素來聲明您的應(yīng)用具有

android.hardware.usb.accessory這個(gè)特色。

  • 如果你正在使用附加類庫,添加<uses-library>這個(gè)元素用來為類庫特定說明com.android.future.usb.accessory
  • 如果您使用附加類庫,那么您所設(shè)置的最低SDK版本是10級;如果您使用android.harware.usb這個(gè)類的話,您所設(shè)置最低版本的SDK就應(yīng)該為12級。
  • 如果您希望您的應(yīng)用帶有一個(gè)附加USB配件的通知,在您的主activity中為android.hardware.usb.action.USB_ACCESSORY_ATTACHED這個(gè)意圖指定一對<intent-filter><meta-data>元素。這個(gè)<meta-data>元素指向一個(gè)額外的聲明關(guān)于你希望探測到的配件的識別信息的XML資源文件。

???在這個(gè)XML資源文件中,為您希望過濾的配件聲明<usb-accessory>元素。每一個(gè)<usb-accessory>都有下面的屬性:

  • 制造商
  • 模式
  • 版本

res/xml/這個(gè)目錄下保存資源文件。這個(gè)資源文件的名字(沒有 .xml的拓展名)必須和你在<meta-data>元素指定的一樣。這個(gè)XML資源文件的格式在下面的例子中給出。

清單和資源文件例子

下面的例子就為您展示了一個(gè)簡單的manifest以及與之相關(guān)的資源文件:

?

??<manifest?...>

????<uses-feature?android:name="android.hardware.usb.accessory"?/>

?

????<uses-sdk?android:minSdkVersion="<version>" />

????...

????<application>

??????<uses-library android:name="com.android.future.usb.accessory" />

????????<activity ...>

????????????...

????????????<intent-filter>

????????????????<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />

????????????</intent-filter>

?

????????????<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"

????????????????android:resource="@xml/accessory_filter" />

????????</activity>

????</application>

??</manifest>

在這種情況之下,下面的資源文件保存在res/xml/accessory_filter.xml文件中,并且指定那些只有與其相關(guān)的模式,制造商和版本的配件能夠被選擇。這個(gè)配件把這些屬性傳遞給搭載Android系統(tǒng)的設(shè)備:

?

<?xml?version="1.0"?encoding="utf-8"?>

?

<resources>

????<usb-accessory?model="DemoKit"?manufacturer="Google"?version="1.0"/>

</resources>

?

用配件工作

?

當(dāng)用戶將USB配件連接到搭載Android系統(tǒng)的設(shè)備上面時(shí),Android系統(tǒng)會判斷您的應(yīng)用是否適用于已連接的該配件。如果適用,您就可以根據(jù)您的喜好為該設(shè)備建立連接。要這么做,您的應(yīng)用必須做下面這些動作:

  • 您需要通過一個(gè)可以過濾配件附加事件的意圖過濾器或者枚舉已連接的配件來發(fā)現(xiàn)連接的配件來找到合適的接口。
  • 尚未獲得許可的用戶在適用配件操作時(shí)需要驗(yàn)證權(quán)限。
  • 通過在接入的端點(diǎn)進(jìn)行讀寫數(shù)據(jù)的操作達(dá)到和配件交互的目的。
  • 發(fā)現(xiàn)配件

    您的應(yīng)用可以通過兩種方式來發(fā)現(xiàn)配件,一種是用一個(gè)意圖過濾器在用戶連接一個(gè)配件時(shí)對其進(jìn)行通知,另一種則是通過枚舉您已經(jīng)連接的所有配件。如果您希望您的應(yīng)用能夠自動的探測到你想要的配件,請使用一個(gè)意圖過濾器來做。但是,如果您希望得到一個(gè)已連接配件的列表或者您不希望過濾意圖,枚舉所有的配件會是一個(gè)更好的選擇。

    使用一個(gè)意圖過濾器

    為了讓您的應(yīng)用可以發(fā)現(xiàn)一個(gè)特定的USB配件,您可以為android.hardware.usb.action.USB_ACCESSORY_ATTACHED這個(gè)意圖指定一個(gè)意圖來進(jìn)行過濾。伴隨著這個(gè)意圖過濾器,您需要指定一個(gè)資源文件來特別說明這個(gè)USB配件的屬性,例如制造商,模式和版本。當(dāng)用戶連接到一個(gè)符合您配件過濾條件的配件時(shí),

    下面的例子告訴您該如何聲明這個(gè)意圖過濾器:

    ?

    <activity?...>

    ????...

    ????<intent-filter>

    ????????<action?android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"?/>

    ????</intent-filter>

    ?

    ????<meta-data?android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"

    ????????android:resource="@xml/accessory_filter"?/>

    </activity>

    ?

    下面的例子告訴您怎么樣聲明指定您希望連接的USB配件的相關(guān)資源文件:

    ?

    <?xml?version="1.0"?encoding="utf-8"?>

    ?

    <resources>

    ????<usb-accessory?manufacturer="Google, Inc."?model="DemoKit"?version="1.0"?/>

    </resources>

    ?

    在您的activity文件中,您可以從像這樣的意圖(有附加類的)中獲取UsbAccessory來代表這個(gè)相關(guān)的配件:

    ?

    UsbAccessory accessory = UsbManager.getAccessory(intent);

    ?

    或者像這樣(用平臺APIs的):

    ?

    UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

    ?

    枚舉所有配件

    您可以使您的應(yīng)用在運(yùn)行時(shí)列舉出所有能夠被識別的配件。

    通過getAccessoryList()方法來獲得一個(gè)包含所有已連接USB配件的數(shù)組:

    ?

    UsbManager manager = (UsbManager)?getSystemService(Context.USB_SERVICE);

    UsbAccessory[]?accessoryList = manager.getAcccessoryList();

    ?

    注意:現(xiàn)在,只能一次連接一個(gè)USB配件操作,但是在以后的API中會支持多配件的操作的。

    獲得使用一個(gè)配件的權(quán)限

    在您使用一個(gè)配件前,您的應(yīng)用必須從用戶那里獲得權(quán)限。

    注意:如果您的應(yīng)用在連接配件時(shí)通過一個(gè)意圖過濾器來發(fā)現(xiàn)它們,如果用戶允許您的應(yīng)用來處理這個(gè)意圖,它將自動接收這個(gè)權(quán)限。如果用戶不允許,那么您就必須在連接配件之前詳細(xì)在您的應(yīng)用中寫明需要請求的權(quán)限。

    在某些情況下很有必要明確權(quán)限的許可要求,例如當(dāng)您的應(yīng)用枚舉出所有已經(jīng)連接的配件并且您希望和其中的一個(gè)進(jìn)行交流。您必須在和該配件交流前檢查是否有連接該配件的權(quán)限。如果不是這樣,您的應(yīng)用將在用戶拒絕您連接該配件的權(quán)限之后收到個(gè)運(yùn)行錯(cuò)誤。

    為了確切地獲得權(quán)限,首先需要?jiǎng)?chuàng)建個(gè)廣播接收器。這個(gè)接收器在您調(diào)用requestPermission()這個(gè)方法時(shí)從您得到的廣播中艦艇這個(gè)意圖。通過調(diào)用requestPermission()這個(gè)方法為用戶跳出一個(gè)是否連接配件的對話框。下面的例子告訴您如何創(chuàng)建一個(gè)廣播接收器:

    ?

    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中的onCreate()方法中去:

    ?

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

    ?

    當(dāng)您需要展示征求用戶同意連接這個(gè)配件的權(quán)限的對話框時(shí),調(diào)用requestPermission()這個(gè)方法:

    ?

    UsbAccessory accessory;

    ...

    mUsbManager.requestPermission(accessory, mPermissionIntent);

    ?

    當(dāng)用戶回應(yīng)這個(gè)對話框時(shí),你的廣播接收器就會收到一個(gè)包含用一個(gè)boolean值來表示結(jié)果的EXTRA_PERMISSION_GRANTED字段的意圖。在您連接配件之前檢查這個(gè)字段的值是否為true

    和配件之間的交流

    您可以通過使用UsbManager這個(gè)類和配件進(jìn)行交流,通過這個(gè)類可以獲得一個(gè)文件描述符,然后您可以利用這個(gè)描述符來設(shè)置輸入和輸出流來讀取和寫入數(shù)據(jù)。這些流用來代表輸入和輸出的批量端點(diǎn)。您最好另起一個(gè)線程來讓您的設(shè)備和配件進(jìn)行交流,因?yàn)檫@樣您就可以不需要將主線程鎖起來了。下面的例子告訴您該如何和一個(gè)配件進(jìn)行交流

    ?

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

    ????}

    }

    ?

    在這個(gè)線程的run()方法中,您可以通過FileInputStream或者FileOutputStream對象來對配件進(jìn)行讀取和寫出數(shù)據(jù)操作。當(dāng)您通過FileInputStream對象讀取配件中的數(shù)據(jù)時(shí),請確保您所使用的緩存能夠存儲下USB數(shù)據(jù)包數(shù)據(jù)。Android配件協(xié)議支持?jǐn)?shù)據(jù)包支持高達(dá)16384字節(jié)的數(shù)據(jù)包緩存區(qū),所以您可以選擇一直讓您的緩存區(qū)是這個(gè)簡單的大小。

    注意:在一個(gè)比較低的水平下,64字節(jié)的數(shù)據(jù)包是全速配件以及512字節(jié)的數(shù)據(jù)包是高速配件。Android配件協(xié)議將這兩種速度捆綁成一個(gè)簡單的邏輯數(shù)據(jù)包。

    想要知道更多如何使用Android中多線程的信息,請參見進(jìn)程和線程

    中止和配件的交流

    當(dāng)您在完成和配件的交流之后,又或者該配件被移除了,通過調(diào)用close()方法來關(guān)閉你已經(jīng)打開的文件描述符。為了監(jiān)聽分離這樣的事件,您需要?jiǎng)?chuàng)建一個(gè)如下的廣播接收器:

    ?

    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

    ????????????}

    ????????}

    ????}

    };

    ?

    ?

    ?

    USB主機(jī)

    文檔內(nèi)容

    • API概述
    • Androidmanifest文件需求
    • 工作的設(shè)備
      • 發(fā)現(xiàn)設(shè)備
      • 獲得和設(shè)備進(jìn)行交流的權(quán)限
      • 和設(shè)備進(jìn)行交流
      • 中止和設(shè)備的交流

    相關(guān)例子

    • Adb測試用例
    • 相關(guān)鏈接

    當(dāng)您搭載Android系統(tǒng)的設(shè)備處于USB主機(jī)模式時(shí),它就像一個(gè)USB主機(jī),為總線提供能源,并且列舉出所有已經(jīng)連接上的設(shè)備。在Android 3.1或者更高的版本中支持USB主機(jī)模式。

    API概述

    在您開始之前,有個(gè)很重要的一點(diǎn)就是您必須對將要用到的類有個(gè)了解。下面的表格就向您描述了在android.hardware.usb這個(gè)包下USB主機(jī)APIs的一些特點(diǎn)。

    1.USB主機(jī)APIs

    Class/Interface

    Description

    UsbManager

    允許您枚舉已連接的USB設(shè)備并且與其進(jìn)行交流

    UsbDevice

    代表了一個(gè)已連接的USB的設(shè)備并且包含具有該設(shè)備驗(yàn)證信息,接口和接入點(diǎn)的方法。

    UsbInterface

    代表了一個(gè)USB設(shè)備的一個(gè)接口,該接口定義了一系列關(guān)于設(shè)備的函數(shù)。一個(gè)設(shè)備在進(jìn)行交流的時(shí)候可以有一個(gè)或者多個(gè)接口。

    UsbEndpoint

    代表一個(gè)接口的接入點(diǎn),該接入點(diǎn)就是這個(gè)接口的通信信道。一個(gè)接口可以有一個(gè)或者多個(gè)這樣的接入點(diǎn),而且一般都是有輸入和輸出雙向通信的接入點(diǎn)。

    UsbDeviceConnection

    代表該設(shè)備的一個(gè)連接,用來在接入點(diǎn)上傳輸數(shù)據(jù)。這個(gè)類允許您能用同步或者異步的方式發(fā)送和返回?cái)?shù)據(jù)。

    UsbRequest

    在通過UsbDeviceConnection和設(shè)備進(jìn)行交流的一個(gè)異步請求。

    UsbConstants

    關(guān)于在linux內(nèi)核中linux/usb/ch9.h的相關(guān)定義的USB常量。

    在大多數(shù)的情況之下,在和一個(gè)USB設(shè)備進(jìn)行交流時(shí),上面這些類都需要用到(UsbRequest這個(gè)類只有在您做異步通信的時(shí)候才會用到)。一般來說,您可以通過查詢要操作的UsbDevice來獲得一個(gè)UsbManager。當(dāng)您有這個(gè)設(shè)備時(shí),您需要找到正確的UsbInterface以及和這個(gè)接口所對應(yīng)的UsbEndpoint來進(jìn)行和設(shè)備的交流。一旦您獲得了正確的接入點(diǎn),打開UsbDeviceConnection來和該USB設(shè)備進(jìn)行交流

    Androidmanifest文件的需求

    下面的列表就是描述您應(yīng)該在用USB主機(jī)APIs之前應(yīng)該在您的應(yīng)用中的manifest文件中添加些什么:

    • 因?yàn)椴皇撬械拇钶dAndroid系統(tǒng)的設(shè)備都能保證支持USB主機(jī)的APIs,不能包含那個(gè)聲明您的應(yīng)用使用android.hardware.usb.host這一特點(diǎn)的android.hardware.usb.host的這一元素。
    • 設(shè)置您的應(yīng)用的最低的SDK版本在12級或者更高。這個(gè)USB主機(jī)APIs不在更前面的版本之中。
    • 如果您希望您的應(yīng)用能夠被連接的USB設(shè)備所提示,只要在您的主activity中在<intent-filter><meta-data>元素對中添加一個(gè)android.hardware.usb.action.USB_DEVICE_ATTACHED意圖。<meta-data>元素指向一個(gè)額外的XML資源文件,該文件是用來聲明驗(yàn)證您希望探測到的設(shè)備的驗(yàn)證信息。

    ???在這個(gè)XML資源文件中,為您希望過濾的USB設(shè)備聲明<usb-device>元素。下面的列表描述<usb-device>的屬性。一般來說,如果您想為一個(gè)特定的設(shè)備過濾就使用該產(chǎn)品的供應(yīng)商和產(chǎn)品ID,如果您希望為一組USB設(shè)備,例如大量存儲設(shè)備或者是數(shù)碼相機(jī)來進(jìn)行過濾那么就應(yīng)該用類,子類和協(xié)議。您可以不指定這些屬性,也可以指定所有的屬性。不為每個(gè)設(shè)備指定屬性,只有在您的應(yīng)用需要它時(shí)才這么做(這句話翻譯的一點(diǎn)問題^_^):

    • 供應(yīng)商ID
    • 產(chǎn)品ID
    • 子類
    • 協(xié)議(設(shè)備或者借口)

    ???將您的資源文件保存到res/xml/目錄下。資源文件名(不包含.xml的擴(kuò)展名)必須和您在<meta-data>元素中指明的那個(gè)名字。在下面的例子中是這個(gè)XML資源文件的格式。

    Manifest文件和資源文件的例子

    下面的例子告訴您一個(gè)manifest文件以及與它相關(guān)資源文件的例子:

    ?

    <manifest?...>

    ????<uses-feature?android:name="android.hardware.usb.host"?/>

    ????<uses-sdk?android:minSdkVersion="12"?/>

    ????...

    ????<application>

    ????????<activity?...>

    ????????????...

    ????????????<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>

    ?

    在這種情況下,下面的資源文件應(yīng)該被保存在res/xml/device_filter.xml來確保找到那些特定符合您要求屬性的USB設(shè)備:

    ?

    <?xml?version="1.0"?encoding="utf-8"?>

    ?

    <resources>

    ????<usb-device?vendor-id="1234"?product-id="5678"?class="255"?subclass="66"?protocol="1"?/>

    </resources>

    ?

    用配件工作

    當(dāng)用戶將USB配件連接到搭載Android系統(tǒng)的設(shè)備上面時(shí),Android系統(tǒng)會判斷您的應(yīng)用是否適用于已連接的該配件。如果適用,您就可以根據(jù)您的喜好為該設(shè)備建立連接。要這么做,您的應(yīng)用必須做下面這些動作:

  • 您需要通過一個(gè)可以過濾USB設(shè)備附加事件的意圖過濾器或者枚舉已連接的USB設(shè)備來發(fā)現(xiàn)連接的配件來找到合適的接口。
  • 尚未獲得許可的用戶在適用USB設(shè)備操作時(shí)需要驗(yàn)證權(quán)限。
  • 通過在接入的端點(diǎn)進(jìn)行讀寫數(shù)據(jù)的操作達(dá)到和USB設(shè)備交互的目的。
  • 發(fā)現(xiàn)設(shè)備

    您的應(yīng)用可以通過兩種方式來發(fā)現(xiàn)USB設(shè)備,一種是用一個(gè)意圖過濾器在用戶連接一個(gè)設(shè)備時(shí)對其進(jìn)行通知,另一種則是通過枚舉您已經(jīng)連接的所有USB設(shè)備。如果您希望您的應(yīng)用能夠自動的探測到你想要的設(shè)備,請使用一個(gè)意圖過濾器來做。但是,如果您希望得到一個(gè)已連接設(shè)備的列表或者您不希望過濾意圖,枚舉所有的設(shè)備會是一個(gè)更好的選擇。

    使用一個(gè)意圖過濾器

    為了讓您的應(yīng)用可以發(fā)現(xiàn)一個(gè)特定的USB設(shè)備,您可以為android.hardware.usb.action.USB_DEVICE_ATTACHED這個(gè)意圖指定一個(gè)意圖來進(jìn)行過濾。伴隨著這個(gè)意圖過濾器,您需要指定一個(gè)資源文件來特別說明這個(gè)USB設(shè)備的屬性,例如供應(yīng)商和產(chǎn)品ID。當(dāng)用戶連接到一個(gè)符合您配件過濾條件的配件時(shí),這個(gè)系統(tǒng)會談出一個(gè)對話框詢問他們是否希望開始您的應(yīng)用。如果用戶同意,那么您的應(yīng)用在失去連接之前會自動獲取和設(shè)備連接的權(quán)限。

    下面的例子告訴您該如何聲明這個(gè)意圖過濾器:

    ?

    <activity?...>

    ...

    ????<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>

    ?

    下面的例子告訴您怎么樣聲明指定您希望連接的USB設(shè)備的相關(guān)資源文件:

    ?

    <?xml?version="1.0"?encoding="utf-8"?>

    ?

    <resources>

    ????<usb-device?vendor-id="1234"?product-id="5678"?/>

    </resources>

    ?

    在您的activity文件中,您可以從像這樣的意圖(有附加類的)中獲取UsbDevice來代表這個(gè)相關(guān)的配件:

    ?

    UsbDevice device = (UsbDevice)?intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

    ?

    枚舉所有配件

    您可以使您的應(yīng)用在運(yùn)行時(shí)列舉出所有能夠被識別的USB設(shè)備。通過getDeviceList()方法來獲得一個(gè)包含所有已連接USB配件的數(shù)組:

    ?

    UsbManager manager = (UsbManager)?getSystemService(Context.USB_SERVICE);

    ... ?

    HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

    UsbDevice device = deviceList.get("deviceName");

    ?

    如果您喜歡,您也可以一個(gè)接一個(gè)的從每一個(gè)設(shè)備的哈希圖和過程中獲取一個(gè)迭代器:

    ?

    UsbManager manager = (UsbManager)?getSystemService(Context.USB_SERVICE);

    ...

    HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

    Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

    while(deviceIterator.hasNext()){

    ????UsbDevice device = deviceIterator.next()

    ????//your code

    }

    ?

    獲得使用一個(gè)配件的權(quán)限

    在您使用一個(gè)USB設(shè)備前,您的應(yīng)用必須從用戶那里獲得權(quán)限。

    注意:如果您的應(yīng)用在連接USB設(shè)備時(shí)通過一個(gè)意圖過濾器來發(fā)現(xiàn)它們,如果用戶允許您的應(yīng)用來處理這個(gè)意圖,它將自動接收這個(gè)權(quán)限。如果用戶不允許,那么您就必須在連接設(shè)備之前詳細(xì)在您的應(yīng)用中寫明需要請求的權(quán)限。

    在某些情況下很有必要明確權(quán)限的許可要求,例如當(dāng)您的應(yīng)用枚舉出所有已經(jīng)連接的USB設(shè)備并且您希望和其中的一個(gè)進(jìn)行交流。您必須在和該設(shè)備交流前檢查是否有連接該設(shè)備的權(quán)限。如果不是這樣,您的應(yīng)用將在用戶拒絕您連接該設(shè)備的權(quán)限之后收到個(gè)運(yùn)行錯(cuò)誤。

    為了確切地獲得權(quán)限,首先需要?jiǎng)?chuàng)建個(gè)廣播接收器。這個(gè)接收器在您調(diào)用requestPermission()這個(gè)方法時(shí)從您得到的廣播中監(jiān)聽這個(gè)意圖。通過調(diào)用requestPermission()這個(gè)方法為用戶跳出一個(gè)是否連接該設(shè)備的對話框。下面的例子告訴您如何創(chuàng)建一個(gè)廣播接收器:

    ?

    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)?{

    ????????????????UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

    ?

    ????????????????if?(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))?{

    ????????????????????if(device?!= null){

    ??????????????????????//call method to set up device communication

    ???????????????????}

    ????????????????}?

    ????????????????else?{

    ????????????????????Log.d(TAG, "permission denied for device "?+ device);

    ????????????????}

    ????????????}

    ????????}

    ????}

    };

    ?

    為了注冊您的廣播接收器,將其放在您activity中的onCreate()方法中去:

    ?

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

    ?

    當(dāng)您需要展示征求用戶同意連接這個(gè)設(shè)備的權(quán)限的對話框時(shí),調(diào)用requestPermission()這個(gè)方法:

    ?

    UsbDevice device;

    ...

    mUsbManager.requestPermission(device, mPermissionIntent);

    ?

    當(dāng)用戶回應(yīng)這個(gè)對話框時(shí),你的廣播接收器就會收到一個(gè)包含用一個(gè)boolean值來表示結(jié)果的EXTRA_PERMISSION_GRANTED字段的意圖。在您連接設(shè)備之前檢查這個(gè)字段的值是否為true

    和設(shè)備之間的交流

    我們可以同步或者異步的和USB設(shè)備進(jìn)行交流。在任意一種情況之下,您都應(yīng)該創(chuàng)建一個(gè)新的線程來進(jìn)行數(shù)據(jù)傳輸,這樣就不會阻塞您的主線程了。要想正確的設(shè)置好和一個(gè)設(shè)備之間的連接,您需要獲得該設(shè)備正確的UsbInterfaceUsbEndpoint來和您進(jìn)行交流以及通過UsbDeviceConnection在這個(gè)接入點(diǎn)上發(fā)送請求。一般來說,您的代碼應(yīng)該這樣:

    • 檢查一個(gè)UsbDevice對象的屬性,例如產(chǎn)品ID,供應(yīng)商ID,或者是關(guān)于設(shè)備的類,以此來確認(rèn)您是否希望和該設(shè)備進(jìn)行交流
    • 當(dāng)您確信您希望和該設(shè)備進(jìn)行交流時(shí),找到關(guān)于該設(shè)備正確的UsbInterface以及和該接口所對應(yīng)的UsbEndpoint。接口可以有一個(gè)或者多個(gè)接入點(diǎn),而且一般都會有一個(gè)雙向通信的輸入和輸出接入點(diǎn)。
    • 當(dāng)您找到正確的接入點(diǎn)時(shí),在該接入點(diǎn)時(shí)打開一個(gè)UsbDeviceConnection
    • 您可以通過bulkTransfer()controlTransfer()這兩個(gè)方法在接入點(diǎn)上傳輸您所需要傳遞的數(shù)據(jù)。您最好在另起一個(gè)新的線程來進(jìn)行這個(gè)步驟以避免阻塞主線程。想要詳細(xì)地了解關(guān)于Android中使用線程的信息,詳見線程和進(jìn)程

    下面的代碼段是做同步數(shù)據(jù)傳輸?shù)囊粋€(gè)簡單方式。您的代碼應(yīng)該有更多的邏輯來準(zhǔn)確地找到和設(shè)備交流的接口和接入點(diǎn),而且應(yīng)該能夠在不同于主線程的線程中能夠傳輸任何的數(shù)據(jù)傳輸。

    ?

    private?Byte[]?bytes

    private?static?int?TIMEOUT = 0;

    private?boolean?forceClaim = true;

    ?

    ...

    ?

    UsbInterface?intf = device.getInterface(0);

    UsbEndpoint endpoint = intf.getEndpoint(0);

    UsbDeviceConnection connection = mUsbManager.openDevice(device);

    connection.claimInterface(intf, forceClaim);

    connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

    ?

    為了能夠異步傳輸數(shù)據(jù),使用UsbRequest類來初始隊(duì)列化一個(gè)異步請求,然后等待requestWait()方法的結(jié)果。

    想要了解更多地信息,請您參考Adb Test sample,這個(gè)參考將會告訴您如何進(jìn)行異步批量傳輸,還有MissleLauncher sample將會告訴您如何異步監(jiān)聽一個(gè)中斷端點(diǎn)。

    中止和設(shè)備的交流

    當(dāng)您在完成和設(shè)備的交流之后,又或者該設(shè)備被移除了,通過調(diào)用releaseInterface()close()的方法來關(guān)閉UseInterfaceUsbDeviceConnection。為了監(jiān)聽分離這樣的事件,您需要?jiǎng)?chuàng)建一個(gè)如下的廣播接收器:

    ?

    BroadcastReceiver mUsbReceiver = new?BroadcastReceiver()?{

    ????public?void?onReceive(Context?context, Intent intent)?{

    ????????String?action = intent.getAction();

    ?

    ??????if?(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))?{

    ????????????UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

    ????????????if?(device?!= null)?{

    ????????????????// call your method that cleans up and closes communication with the device

    ????????????}

    ????????}

    ????}

    };

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/lsy-2016/p/7286127.html

    與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的usb附件连接方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。