【背景】
折腾:
【已解决】Android设备作为Host希望实现可以检测到USB设备插入
期间,需要实现:
android程序在运行期间,可以检测到usb设备的插入。
但是却出现:
android程序运行时可以检测到ACTION_USB_DEVICE_DETACHED:
但是检测不到ACTION_USB_DEVICE_ATTACHED
【折腾过程】
1.去参考:
去试试:
AndroidManifest.xml
中添加:
1 2 3 4 | < application ... <receiver android:name = "UsbDeviceStateReceiver" /> <!-- <receiver android:name="usbDeviceStateReceiver" /> --> |
看看效果。
2.不过,参考之前就看到的:
Android 3.1 USB-Host – BroadcastReceiver does not receive USB_DEVICE_ATTACHED
有点明白了:
app,正在运行
USB设备插入
系统检测到ACTION_USB_DEVICE_ATTACHED
但是不会发送给你的当前的app的当前页面
而是:发送给你的app的activity的onResume()
并且是:
即使你在
onResume()
去检测
UsbManager.ACTION_USB_DEVICE_ATTACHED
也还是检测不到的。。。
而是:
该intent会回来(??)变成android.intent.action.MAIN的
3.不过,对于
ACTION_USB_DEVICE_DETACHED
参考:
USB host has confusing documentation
说是:
暂时android有bug,所以,通过代码中去检测:
ACTION_USB_DEVICE_DETACHED
而检测不到。
暂时只能通过:
Manifest文件中去检测
如果是这样的话:
那也忒坑爹了。。。。
关键我就是只需要:
在代码运行时检测usb插入
而不需要程序没运行时,去检测USB插入。。。
5.然后,果然在:
USB host device plugin notification failure
看到,的确是个bug,且暂时还没解决掉。。。。
坑爹。。。
6.评论中,robin说是提交个patch解决了此问题,
然后参考那人的patch:
https://android-review.googlesource.com/#/c/38150/
->
看到是:
// Send broadcast to running activity with registered intent mContext.sendBroadcast(intent); // Start activity with registered intent |
7.郁闷了。
因为刚刚测试了如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); ... detectUsbDeviceAttach(); } @Override public void onResume() { super .onResume(); Intent intent = getIntent(); String curItentActionName = intent.getAction(); Toast.makeText(getApplicationContext(), String.valueOf( "Into onResume" ), 1000 ).show(); Toast.makeText(getApplicationContext(), String.valueOf( "curItentActionName=" + curItentActionName), 1000 ).show(); Toast.makeText(getApplicationContext(), String.valueOf( "bUsbConnected=" + bUsbConnected), 1000 ).show(); if (bUsbConnected== false ) { //check to see if USB is now connected } } // BroadcastReceiver when remove the device USB plug from a USB port BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 Toast.makeText(context, String.valueOf( "Into UsbDeviceStateReceiver !" ), 1000 ).show(); String curItentActionName = intent.getAction(); Toast.makeText(context, String.valueOf( "Current Intent Action: " + curItentActionName), 1000 ).show(); if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(curItentActionName)){ Toast.makeText(context, String.valueOf( "Found USB Device attached +++DEVICE+++ !" ), 1000 ).show(); Toast.makeText(context, String.valueOf( "Component: " + intent.getComponent()), 1000 ).show(); Toast.makeText(context, String.valueOf( "Aciton: " + intent.getAction()), 1000 ).show(); Toast.makeText(context, String.valueOf( "Categories: " + intent.getCategories()), 1000 ).show(); Toast.makeText(context, String.valueOf( "Data: " + intent.getData()), 1000 ).show(); Toast.makeText(context, String.valueOf( "DataType: " + intent.getType()), 1000 ).show(); Toast.makeText(context, String.valueOf( "DataSchema: " + intent.getScheme()), 1000 ).show(); UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE); HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); while (deviceIterator.hasNext()){ UsbDevice device = deviceIterator.next(); int usbVid = device.getVendorId(); int usbPid = device.getProductId(); if ((usbVid == ft232rUartVid) && (usbPid ==ft232rUartPid) ){ Toast.makeText(context, "Found Usb device: FT232R UART" , Toast.LENGTH_LONG).show(); break ; } } } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(curItentActionName)){ bUsbConnected = false ; Toast.makeText(context, String.valueOf( "Found USB Device detached ---DEVICE--- !" ), 1000 ).show(); } else if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(curItentActionName)){ Toast.makeText(context, String.valueOf( "Found USB accessory attached +++ACCESSORY+++ !" ), 1000 ).show(); } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(curItentActionName)){ Toast.makeText(context, String.valueOf( "Found USB accessory detached ---ACCESSORY---!" ), 1000 ).show(); } else { Toast.makeText(context, String.valueOf( "Unrecoginzed action !" ), 1000 ).show(); } } }; private void detectUsbDeviceAttach(){ //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 //final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; //listen usb device attach IntentFilter usbDeviceStateFilter = new IntentFilter(); //usbDeviceStateFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); //usbDeviceStateFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); //usbDeviceStateFilter.addDataScheme("file"); usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED); //usbDeviceStateFilter.addAction(ACTION_USB_PERMISSION); //UsbDeviceStateReceiver usbDeviceStateReceiver = new UsbDeviceStateReceiver(); //registerReceiver(usbDeviceStateReceiver, usbDeviceStateFilter); registerReceiver(mUsbReceiver, usbDeviceStateFilter); // UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); // // HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); // Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); // while(deviceIterator.hasNext()){ // UsbDevice device = deviceIterator.next(); // int usbVid = device.getVendorId(); // int usbPid = device.getProductId(); // if((usbVid == ft232rUartVid) && (usbPid ==ft232rUartPid) ){ // Toast.makeText(getApplicationContext(), "Found Usb device: FT232R UART", Toast.LENGTH_LONG).show(); // break; // } // } } |
结果是:
USB设备插入后:
(1)根本没有进入那个所谓的onResume
(2)的确是UsbSettingsManager.java中的bug,使得app收不到对应的UsbManager.ACTION_USB_DEVICE_ATTACHED
(3)USB设备拔出,倒是一直可以正常检测到的。
【总结】
然后结论是:
1.如果是在AndroidManifest.xml加入:
1 2 3 4 5 | < intent-filter > < action android:name = "android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </ intent-filter > < meta-data android:name = "android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource = "@xml/usbserial" /> |
以及在
res/xml/usbserial.xml
加上对应的vid和pid的配置:
1 2 3 4 5 6 7 8 9 10 | < resources > <!-- 0x0403 / 0x6001: FTDI FT232R UART --> < usb-device vendor-id = "1027" product-id = "24577" /> <!-- 0x2341 / Arduino --> < usb-device vendor-id = "9025" /> <!-- 0x16C0 / 0x0483: Teensyduino --> < usb-device vendor-id = "5824" product-id = "1155" /> <!-- 0x10C4 / 0xEA60: CP210x UART Bridge --> < usb-device vender-id = "4292" product-id = "60000" /> </ resources > |
然后对于USB device的插入,Android系统可以检测到,会弹出对应的对话框,问你是否打开你的程序的。
对于USB拔掉的UsbManager.ACTION_USB_DEVICE_DETACHED
更加可以正常工作。
2.但是想要在:
程序正常运行时,去检测
UsbManager.ACTION_USB_DEVICE_ATTACHED
目前无法实现。
因为是android系统有bug:
android 4.2(甚至是4.3)之前(包括:4.0.3,4.1,4.2等等),全部都是:
server/usb/UsbSettingsManager.java
中存在bug:
使得对于插入USB设备的事件,获得不到对应的indent。
(USB设备拔掉,倒是可以获得对应的UsbManager.ACTION_USB_DEVICE_DETACHED)
导致:
我这里,只需要关心,程序在执行期间,检测usb设备插入(对于usb设备拔出我不关心)
却没发很简单的实现。。。
需要以后考虑别的方案了。。。。
坑爹啊。。。
【后记】
后续折腾,详见:
【已解决】Android设备作为Host希望实现可以检测到USB设备插入
转载请注明:在路上 » 【未解决】android程序运行时可以检测到ACTION_USB_DEVICE_DETACHED,但是检测不到ACTION_USB_DEVICE_ATTACHED