【背景】
折腾:
【已解决】Android设备作为Host希望实现可以检测到USB设备插入
期间,需要实现:
android程序在运行期间,可以检测到usb设备的插入。
但是却出现:
android程序运行时可以检测到ACTION_USB_DEVICE_DETACHED:
但是检测不到ACTION_USB_DEVICE_ATTACHED
【折腾过程】
1.去参考:
去试试:
AndroidManifest.xml
中添加:
<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.郁闷了。
因为刚刚测试了如下代码:
@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加入:
<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的配置:
<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