Android USB 开发详解
Android USB 開發(fā)詳解
先附上?Android USB 官方文檔
Android通過兩種模式支持各種 USB 外設(shè)和 Android USB 附件(實(shí)現(xiàn)Android附件協(xié)議的硬件):USB附件和USB主機(jī)。USB開發(fā)需 Android 3.1(API級(jí)別12)以上。由于本人工作中只用到了主機(jī)模式,所以本文的側(cè)重點(diǎn)在主機(jī)模式開發(fā)。
- Android USB 開發(fā)詳解
- 調(diào)試
- 一、AndroidManifest 文件設(shè)置
- 二、USB 設(shè)備的連接和使用
- 1.Android 中的 USB
- 2.USB 設(shè)備的插入
- 3.獲取 UsbManager
- 4.獲取 USB 設(shè)備列表
- 5.獲取特定的設(shè)備
- 6.申請(qǐng) USB 設(shè)備使用權(quán)限
- 7.通信
- 其他
調(diào)試
在使用 USB 連接設(shè)備調(diào)試的時(shí)候,USB 外設(shè)將不能連接至設(shè)備,可以使用 WIFI 的方式連接調(diào)試,settings -> plugin -> WiFi ADB 插件好幾個(gè),選個(gè)適合自己的就 OK。
或者…我這里正好有一篇Android 模擬器連接 USB 設(shè)備喜歡點(diǎn)個(gè)贊哈!
一、AndroidManifest 文件設(shè)置
- uses-feature 申明這個(gè)軟件需要使用 USB 功能,申明這個(gè) Google Play 會(huì)把不滿足的設(shè)備過濾掉,一般用 USB 的都是定制開發(fā),忽略就行
- 1
- 將應(yīng)用程序的最低SDK設(shè)置為API級(jí)別12或更高,早期 API 沒有。
- 如果你希望你的應(yīng)用程序連接指定的 USB 設(shè)備時(shí)被通知,需指定 和 元素對(duì)用于 android.hardware.usb.action.USB_DEVICE_ATTACHED。該 元素指向聲明識(shí)別有關(guān)您要檢測(cè)的設(shè)備信息的外部XML資源文件。
- 在XML資源文件中,聲明要過濾的USB設(shè)備的元素。以下列表描述了屬性 。通常,如果要過濾特定設(shè)備并使用類,子類和協(xié)議(如果要過濾一組USB設(shè)備(如大容量存儲(chǔ)設(shè)備或數(shù)碼相機(jī))),請(qǐng)使用供應(yīng)商(vendor-id)和產(chǎn)品(product-id)ID,在開發(fā)中這些過濾ID一般可以在文檔中找到,或者自己連上看也行。你可以指定部分或全部這些屬性。?
將資源文件保存在res/xml/目錄中。資源文件名(不帶.xml擴(kuò)展名)必須與您在元素中指定的文件名相同 。對(duì)于XML資源文件格式的 例子如下:
?
配置好清單文件后當(dāng)用戶連接與您的設(shè)備過濾器匹配的設(shè)備時(shí),系統(tǒng)會(huì)向他們顯示一個(gè)對(duì)話框,詢問他們是否要啟動(dòng)您的應(yīng)用程序。如果用戶接受,則應(yīng)用程序?qū)?strong>自動(dòng)具有訪問設(shè)備的權(quán)限,直到設(shè)備斷開連接。如果給了默認(rèn),那么這個(gè) USB 設(shè)備插入后會(huì)自動(dòng)啟動(dòng)這個(gè) Activity
二、USB 設(shè)備的連接和使用
在清單文件中配置好以后我們直接進(jìn)入 Java 代碼環(huán)節(jié)
1.Android 中的 USB
Android 3.1(API級(jí)別12)以上原生提供了 USB 開發(fā)的 API,在android.hardware.usb包下提供了開發(fā)的相關(guān)類。
| UsbManager | 獲得 USB 管理器,與連接的 USB 設(shè)備通信。 |
| UsbDevice | USB 設(shè)備的抽象,每個(gè)UsbDevice 都代表一個(gè) USB 設(shè)備。 |
| UsbInterface | 定義了設(shè)備的功能集,一個(gè) UsbDevice 可能包含一個(gè)或多個(gè)UsbInterface,每個(gè) Interface 都是獨(dú)立的。 |
| UsbEndpoint | UsbEndpoint 是 interface 的通信通道。 |
| UsbDeviceConnection | host 與 device 建立的連接,并在 endpoint 傳輸數(shù)據(jù)。 |
| UsbRequest | USB 請(qǐng)求包。 |
| UsbConstants | USB 常量的定義 |
2.USB 設(shè)備的插入
Android 系統(tǒng)中,USB 設(shè)備的插入和拔出是以系統(tǒng)廣播的形式發(fā)送的,我們只要注冊(cè)監(jiān)聽這個(gè)廣播就好
public class USBReceiver extends BroadcastReceiver {public static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_USB_PERMISSION.equals(action)) {// 獲取權(quán)限結(jié)果的廣播synchronized (this) {UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device != null) {//call method to set up device communicationif (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {Log.e("USBReceiver", "獲取權(quán)限成功:" + device.getDeviceName());} else {Log.e("USBReceiver", "獲取權(quán)限失敗:" + device.getDeviceName());}}}}else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {// 有新的設(shè)備插入了,在這里一般會(huì)判斷這個(gè)設(shè)備是不是我們想要的,是的話就去請(qǐng)求權(quán)限} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {// 有設(shè)備拔出了}} }?
3.獲取 UsbManager
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);4.獲取 USB 設(shè)備列表
public List<UsbDevice> getDeviceList() {HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();List<UsbDevice> usbDevices = new ArrayList<>();while (deviceIterator.hasNext()) {UsbDevice device = deviceIterator.next();usbDevices.add(device);Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());}return usbDevices;}?
5.獲取特定的設(shè)備
/*** mVendorId=1137,mProductId=85 佳博 3150T 標(biāo)簽打印機(jī)** @param vendorId 廠商ID* @param productId 產(chǎn)品ID* @return device*/public UsbDevice getUsbDevice(int vendorId, int productId) {HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();while (deviceIterator.hasNext()) {UsbDevice device = deviceIterator.next();if (device.getVendorId() == vendorId && device.getProductId() == productId) {Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());return device;}}Toast.makeText(context, "沒有對(duì)應(yīng)的設(shè)備", Toast.LENGTH_SHORT).show();return null;}6.申請(qǐng) USB 設(shè)備使用權(quán)限
安卓系統(tǒng)對(duì) USB 設(shè)備的使用需要得到相應(yīng)的權(quán)限,這個(gè)權(quán)限要用戶手動(dòng)授予,或插入設(shè)備時(shí)應(yīng)用到你的應(yīng)用中。在使用 USB 設(shè)備前首先我們要確認(rèn)一下上一節(jié)中的device是否已經(jīng)獲得權(quán)限,如果沒有就要主動(dòng)申請(qǐng)權(quán)限:
/*** 判斷對(duì)應(yīng) USB 設(shè)備是否有權(quán)限*/public boolean hasPermission(UsbDevice device) {return usbManager.hasPermission(device);}/*** 請(qǐng)求獲取指定 USB 設(shè)備的權(quán)限*/public void requestPermission(UsbDevice device) {if (device != null) {if (usbManager.hasPermission(device)) {Toast.makeText(context, "已經(jīng)獲取到權(quán)限", Toast.LENGTH_SHORT).show();} else {if (mPermissionIntent != null) {usbManager.requestPermission(device, mPermissionIntent);Toast.makeText(context, "請(qǐng)求USB權(quán)限", Toast.LENGTH_SHORT).show();} else {Toast.makeText(context, "請(qǐng)注冊(cè)USB廣播", Toast.LENGTH_LONG).show();}}}}?
注冊(cè)廣播:
public void registerReceiver(Activity context) {mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);context.registerReceiver(usbReceiver, filter);}?
7.通信
與 USB 設(shè)備的通信可以是同步的也可以是異步的。無論哪種情況,你都應(yīng)該創(chuàng)建一個(gè)新線程來執(zhí)行所有數(shù)據(jù)傳輸,避免阻塞UI線程。
第一步,打開通信端口
public boolean openPort(UsbDevice device) {//獲取設(shè)備接口,一般只有一個(gè),多個(gè)的自己研究去usbInterface = device.getInterface(0);// 判斷是否有權(quán)限if (hasPermission(device)) {// 打開設(shè)備,獲取 UsbDeviceConnection 對(duì)象,連接設(shè)備,用于后面的通訊usbConnection = usbManager.openDevice(device);if (usbConnection == null) {return false;}if (usbConnection.claimInterface(usbInterface, true)) {Toast.makeText(Utils.getContext(), "找到 USB 設(shè)備接口", Toast.LENGTH_SHORT).show();} else {usbConnection.close();Toast.makeText(Utils.getContext(), "沒有找到 USB 設(shè)備接口", Toast.LENGTH_SHORT).show();return false;}} else {Toast.makeText(Utils.getContext(), "沒有 USB 權(quán)限", Toast.LENGTH_SHORT).show();return false;}//獲取接口上的兩個(gè)端點(diǎn),分別對(duì)應(yīng) OUT 和 INfor (int i = 0; i < usbInterface.getEndpointCount(); ++i) {UsbEndpoint end = usbInterface.getEndpoint(i);if (end.getDirection() == UsbConstants.USB_DIR_IN) {usbEndpointIn = end;} else {usbEndpointOut = end;}}return true;}?
第二步,發(fā)送數(shù)據(jù)
usbConnection.bulkTransfer(usbEndpointOut, bytes, bytes.length, 500);其他
剩余的 API 我會(huì)在項(xiàng)目不斷完善的同時(shí)更新上來
總結(jié)
以上是生活随笔為你收集整理的Android USB 开发详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高效程序员
- 下一篇: Android USB串口开发