1. 程式人生 > >android 手機通過usb資料線與OTG裝置通訊

android 手機通過usb資料線與OTG裝置通訊

1.首先在AndroidManifest.xml檔案中新增所需要的許可權

<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2.然後在AndroidManifest.xml檔案中的activity下新增以下程式碼

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  <!--加上這句程式碼,手機與OTG裝置連線就會啟動該APP,並跳轉到該activity-->
  <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
<!--在res資料夾下面新建一個 xml的資料夾,然後新建device_filter.xml-->
<meta-data
        android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />
</activity>

3.新建device_filter.xml資料夾

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device
<!--這兩個id由製造提供的-->
        product-id="123"
        vendor-id="1234" />
</resources>

4.在onCreate方法中初始化連線裝置的一些配置,註冊廣播接收裝置斷開與連線的廣播

public static final String ACTION_USB_PERMISSION = "com.test.otg.USB_PERMISSION";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //獲取 USB 管理器
    usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    registerBrasdcast();
    initUsb();
    initView();
}

//初始化裝置

private void initUsb() {
    try { //取連線到裝置上的 USB 裝置集合
        HashMap<String, UsbDevice> map = usbManager.getDeviceList();
        //遍歷集合取指定的 USB 裝置
        for (UsbDevice device : map.values()) {
            Log.i("device", "vid:" + device.getVendorId() + "   pid:" + device.getProductId() + "   " + device.getDeviceName());
            if (1234== device.getVendorId() && 123== device.getProductId()) {
                usbDevice = device;
                if (usbManager.hasPermission(usbDevice)) {
                    usbManager.requestPermission(device, pendingIntent);
                }
                getDeviceInterface();//獲取介面
                assignEndpoint(Interface2);// 分配端點
                openDevice(Interface2);//開啟裝置
            }
        }
        if (usbDevice == null) {
            Log.e("TAG", "沒有獲取到裝置");
            return;
        }
    } catch (Exception e) {
        e.printStackTrace();
        toast("裝置獲取異常");
    }
}
// 尋找裝置介面
private void getDeviceInterface() {
    if (usbDevice != null) {
        Log.i("TAG", "interfaceCounts : " + usbDevice.getInterfaceCount());
        for (int i = 0; i < usbDevice.getInterfaceCount(); i++) {
            UsbInterface intf = usbDevice.getInterface(i);
            if (i == 0) {
                Interface1 = intf; // 儲存裝置介面
                Log.i("TAG", "成功獲得裝置介面:" + Interface1.getId());
            }
            if (i == 1) {
                Interface2 = intf;
                Log.i("TAG", "成功獲得裝置介面:" + Interface2.getId());
            }
        }
    } else {
        Log.e("TAG", "未連線裝置!");
    }
}
// 分配端點,IN /OUT,即輸入輸出;
private UsbEndpoint assignEndpoint(UsbInterface mInterface) {
    for (int i = 0; i < mInterface.getEndpointCount(); i++) {
        UsbEndpoint ep = mInterface.getEndpoint(i);
        if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
            if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                epBulkOut = ep;
            } else {
                epBulkIn = ep;
            }
        }
        if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_CONTROL) {
            epControl = ep;
        }
        if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
            if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                epIntEndpointOut = ep;
            }
            if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
                epIntEndpointIn = ep;
            }
        }
    }
    if (epBulkOut == null && epBulkIn == null && epControl == null
            && epIntEndpointOut == null && epIntEndpointIn == null) {
        throw new IllegalArgumentException("not endpoint is founded!");
    }
    return epIntEndpointIn;
}
// 開啟裝置
public void openDevice(UsbInterface mInterface) {
    if (mInterface != null) {
        UsbDeviceConnection conn = null;
        // 在open前判斷是否有連線許可權;對於連線許可權可以靜態分配,也可以動態分配許可權
        if (usbManager.hasPermission(usbDevice)) {
            conn = usbManager.openDevice(usbDevice);
        } else {
            usbManager.requestPermission(usbDevice, pendingIntent);
        }
        if (conn == null) {
            return;
        }
        if (conn.claimInterface(mInterface, true)) {
            myDeviceConnection = conn;
            // 到此你的android裝置已經連上otg裝置
            if (myDeviceConnection != null)
                System.out.println("開啟裝置成功!");
        } else {
            System.out.println("無法開啟連線通道。");
            conn.close();
        }
    }
}
//廣播註冊
private void registerBrasdcast() {
    //註冊許可權廣播
    IntentFilter usbFilter = new IntentFilter(ACTION_USB_PERMISSION);
    //usb 插入廣播
    usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    //usb 拔出廣播
    usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
    registerReceiver(mUsbReceiver, usbFilter);
}
//廣播接收
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("TAG", intent.getAction());
        switch (intent.getAction()) {
            case UsbManager.ACTION_USB_DEVICE_ATTACHED:
                toast("裝置插入");
                initUsb();//初始化裝置
                break;
            case UsbManager.ACTION_USB_DEVICE_DETACHED:
                toast("裝置斷開");
                break;
            case ACTION_USB_PERMISSION:
                synchronized (this) {
                    UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            openDevice(Interface2);
                        }
                    } else {
                        Toast.makeText(MainActivity.this, "使用者拒絕了USB的許可權!", Toast.LENGTH_LONG).show();
                        return;
                    }
                }
                break;
        }
    }
};

5.傳送與接收資料

//傳送資料
@Override
public void onClick(View v) {
    switch (v.getId()) {
if (myDeviceConnection == null) {
    toast("裝置未連線或未授權!");
    return;
}
// 傳送準備命令
int reto = myDeviceConnection.bulkTransfer(epBulkOut, openDate, openDate.length, 5000);
if (reto != -1) {
    Log.i("TAG", "已經發送資料" + reto);
    Message openMsg = Message.obtain();
    openMsg.what = SEND_DAT;
    mHandler.sendMessage(openMsg);
      }
   }
}
//接收資料
private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
       case SEND_DATA:
byte[] receiverDate= new byte[20];
int rets = myDeviceConnection.bulkTransfer(epBulkIn, receiverDate, 20, 5000);
if(rets!=-1){
//處理收到的receiverDate陣列,16進位制的
}
    }
  }
};

6.解除廣播

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mUsbReceiver);
}

AndroidManifest.xml的activity中沒有加上這段程式碼,連線時總是會彈出允許裝置的視窗,點預設也沒有用。

<intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter>

網上說可以改原始碼,我對原始碼進行修改後也不起作用,暫時不知道怎麼去掉USB的許可權允許窗。