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的权限允许窗。