標籤:
前端時間搗鼓一個HID的硬體, 需要和android通訊, 網上搜尋了一圈,收穫不小.
比較好的文章是:
Android USB Host與HID通訊
Android Service建立USB HOST通訊
其中代碼之處有些地方需要注意的, 特此註明一下:
/** * USB HOST 串連 HID * @author IVAN * */public class MainActivity extends Activity { private static final String TAG = "USB_HOST"; private UsbManager myUsbManager; private UsbDevice myUsbDevice; private UsbInterface myInterface; private UsbDeviceConnection myDeviceConnection; private final int VendorID = 8457; //這裡要改成自己的硬體ID private final int ProductID = 30264; private TextView info; private UsbEndpoint epOut; private UsbEndpoint epIn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); info = (TextView) findViewById(R.id.info); // 擷取UsbManager myUsbManager = (UsbManager) getSystemService(USB_SERVICE); enumerateDevice(); findInterface(); openDevice(); assignEndpoint(); } /** * 分配端點,IN | OUT,即輸入輸出;此處我直接用1為OUT端點,0為IN,當然你也可以通過判斷 */
//USB_ENDPOINT_XFER_BULK
/*
#define USB_ENDPOINT_XFER_CONTROL 0 --控制傳輸
#define USB_ENDPOINT_XFER_ISOC 1 --等時傳輸
#define USB_ENDPOINT_XFER_BULK 2 --塊傳輸
#define USB_ENDPOINT_XFER_INT 3 --中斷傳輸
* */
private void assignEndpoint() {
if (myInterface != null) { //這一句不加的話 很容易報錯 導致很多人在各大論壇問:為什麼報錯呀
//這裡的代碼替換了一下 按自己硬體屬性判斷吧
for (int i = 0; i < myInterface.getEndpointCount(); i++) {
UsbEndpoint ep = myInterface.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else {
epIn = ep;
}
}
}
}
Log.d(TAG, getString(R.string.text)); } /** * 開啟裝置 */ private void openDevice() { if (myInterface != null) { UsbDeviceConnection conn = null; // 在open前判斷是否有串連許可權;對於串連許可權可以靜態分配,也可以動態分配許可權,可以查閱相關資料 if (myUsbManager.hasPermission(myUsbDevice)) { conn = myUsbManager.openDevice(myUsbDevice); } if (conn == null) { return; } if (conn.claimInterface(myInterface, true)) { myDeviceConnection = conn; // 到此你的android裝置已經連上HID裝置 Log.d(TAG, "開啟裝置成功"); } else { conn.close(); } } } /** * 找裝置介面 */ private void findInterface() { if (myUsbDevice != null) { Log.d(TAG, "interfaceCounts : " + myUsbDevice.getInterfaceCount()); for (int i = 0; i < myUsbDevice.getInterfaceCount(); i++) { UsbInterface intf = myUsbDevice.getInterface(i); // 根據手上的裝置做一些判斷,其實這些資訊都可以在枚舉到裝置時列印出來 if (intf.getInterfaceClass() == 8 && intf.getInterfaceSubclass() == 6 && intf.getInterfaceProtocol() == 80) { myInterface = intf; Log.d(TAG, "找到我的裝置介面"); } break; } } } /** * 枚舉裝置 */ private void enumerateDevice() { if (myUsbManager == null) return; HashMap<String, UsbDevice> deviceList = myUsbManager.getDeviceList(); if (!deviceList.isEmpty()) { // deviceList不為空白 StringBuffer sb = new StringBuffer(); for (UsbDevice device : deviceList.values()) { sb.append(device.toString()); sb.append("\n"); info.setText(sb); // 輸出裝置資訊 Log.d(TAG, "DeviceInfo: " + device.getVendorId() + " , " + device.getProductId()); // 枚舉到裝置 if (device.getVendorId() == VendorID && device.getProductId() == ProductID) { myUsbDevice = device; Log.d(TAG, "枚舉裝置成功"); } } } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }}
擷取資料的代碼:
ncount = myDeviceConnection.bulkTransfer(epIn, buffer, buffer.length, 100);
這裡注意資料讀取的長度, 這個對某些硬體來說非常重要, 有的硬體小了或者大了立馬死機重啟, 要麼就是一直返回-1
這個資料的長度需要根據硬體屬性來,
有一種辦法是通過int inMax = epIn.getMaxPacketSize()來擷取;
還有一種辦法是通過windows下面的hid程式探測裝置的資料長度;
至於讀不到硬體的問題 我覺得以下辦法不會有協助了, 要麼是硬體不支援, android4.0以上 貌似都包含了以下的檔案資訊了
將android.hardware.usb.host.xml檔案放到/system/etc/permissions下;第二處是在同目錄下的handheld_core_hardware.xml裡面添加一句<feature name="android.hardware.usb.host">
Android USB Host與HID通訊