Android USB Host与HID通讯

我只是一个虾纸丫 提交于 2020-03-03 08:20:05

前端时间捣鼓一个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">

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!