【背景】
折腾:
【已解决】Android设备作为Host希望实现可以检测到USB设备插入
期间,需要尝试去通过,新建一个线程或进程,然后去动态检测USB设备的插入。
【折腾过程】
1.先去搞懂,android中如何新建线程。
2.官网文档:
https://developer.android.com/reference/java/lang/Thread.html
3.看看:
Android create new thread in service class
去试试。
4.期间出现:
【已解决】android中switch中的case中不用使用enum枚举值:Type mismatch: cannot convert from xxx to int
5.再去继续写代码测试。
然后又遇到:
6.然后用了代码:
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 | usbActionDetectThread = new Thread( new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "Begin check usb action" , 1000 ).show(); 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(); Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity " , Toast.LENGTH_LONG).show(); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); break ; } else { Toast.makeText(getApplicationContext(), "Found USB VID=" +usbVid+ " PID=" + usbPid, Toast.LENGTH_LONG).show(); } } try { Thread.sleep( 200 ); } catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); } } }); usbActionDetectThread.start(); |
结果都没指定到:
run函数里面去。。。
7.参考:
How to Send the Current Thread to Sleep
去改为:
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 | usbActionDetectThread = new Thread() //new Runnable() { { // @Override public void run() { Toast.makeText(getApplicationContext(), "Begin check usb action" , 1000 ).show(); 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(); Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity " , Toast.LENGTH_LONG).show(); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); break ; } else { Toast.makeText(getApplicationContext(), "Found USB VID=" +usbVid+ " PID=" + usbPid, Toast.LENGTH_LONG).show(); } } try { Thread.sleep( 200 ); } catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); } } }; usbActionDetectThread.start(); |
再去试试是否能运行到。
结果还是不行。
8.再改为通过Handler:
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 | //public class DeviceListActivity extends BaseActivity { public class DeviceListActivity extends BaseActivity implements Runnable { @Override public void run() { //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 Toast.makeText(getApplicationContext(), "Begin check usb action" , 1000 ).show(); 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(); Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity " , Toast.LENGTH_LONG).show(); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); break ; } else { Toast.makeText(getApplicationContext(), "Found USB VID=" +usbVid+ " PID=" + usbPid, Toast.LENGTH_LONG).show(); } } } private void usbActionDetectViaHandler(){ mHandler= new Handler() { public void handleMessage(Message msg) { usb_action curUsbAction = usb_action.values()[msg.what]; //do your own bounds checking switch (curUsbAction) { case USB_ACTION_UNKNOWN: Toast.makeText(getApplicationContext(), "Unkown USB action !" , Toast.LENGTH_LONG).show(); break ; case USB_ACTION_ATTACH: //TODO: do auto scan hart devices Toast.makeText(getApplicationContext(), "Now should call the HART auto scan" , Toast.LENGTH_LONG).show(); break ; case USB_ACTION_DETACH: //stop auto detect usb action thread Toast.makeText(getApplicationContext(), "Now destory the usb action detect thread" , Toast.LENGTH_LONG).show(); usbActionDetectThread.destroy(); break ; default : break ; } super .handleMessage(msg); } }; Thread curThread= new Thread( this ); curThread.start(); } |
结果却会出错:
参考:
[Java:Eclipse]JDI thread evaluations:Exception processing async thread queue
去关闭Expressions视图,
重新debug,看看是否还会有该错误。
果然没了该错误了。
但是该运行的代码,还是没运行到。。。
9.参考:
Specifying the Code to Run on a Thread
看到其中关键一句:
Remember, though, that the Runnable won’t be running on the UI thread, |
所以,上述的代码,写在Runnable中的,是没法运行在:
我当前的,本身就是出于UI线程中的。
但是应该是:
的确底层,去新建了线程,去执行对应的代码的。
10.后来发现,上述代码出错了:
1 2 3 4 5 6 7 8 9 | 11-06 16:47:42.988: E/AndroidRuntime(3037): FATAL EXCEPTION: Thread-361 11-06 16:47:42.988: E/AndroidRuntime(3037): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 11-06 16:47:42.988: E/AndroidRuntime(3037): at android.os.Handler.<init>(Handler.java:121) 11-06 16:47:42.988: E/AndroidRuntime(3037): at android.widget.Toast$TN.<init>(Toast.java:347) 11-06 16:47:42.988: E/AndroidRuntime(3037): at android.widget.Toast.<init>(Toast.java:93) 11-06 16:47:42.988: E/AndroidRuntime(3037): at android.widget.Toast.makeText(Toast.java:240) 11-06 16:47:42.988: E/AndroidRuntime(3037): at com.yy.xxx.activities.DeviceListActivity.run(DeviceListActivity.java:298) 11-06 16:47:42.988: E/AndroidRuntime(3037): at java.lang.Thread.run(Thread.java:856) 11-06 16:47:43.386: D/dalvikvm(3037): threadid=1: still suspended after undo (sc=1 dc=1) |
看代码中的:
1 | public void run() { |
很明显是:
第一句就是:
298行的:
1 | Toast.makeText(getApplicationContext(), "Begin check usb action" , 1000 ).show(); |
结果导致了上面的
at com.yy.xxx.activities.DeviceListActivity.run(DeviceListActivity.java:298)
调用makeText出错:
at android.widget.Toast.makeText(Toast.java:240)
的。
11.所以,去参考:
Communicating with the UI Thread
看看如何打印toast。
算了,暂时不打印toast了,改为log算了:
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 | @Override public void run() { //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 //Toast.makeText(getApplicationContext(), "Begin check usb action", 1000).show(); gLogger.debug( "Begin check usb action" ); 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(); //Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity ", Toast.LENGTH_LONG).show(); gLogger.debug( "Found Usb device: FT232R UART" ); gLogger.debug( "Now send message USB_ACTION_ATTACH to activit" ); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); break ; } else { //Toast.makeText(getApplicationContext(), "Found USB VID="+usbVid+" PID=" + usbPid, Toast.LENGTH_LONG).show(); gLogger.debug( "Found USB VID=" +usbVid+ " PID=" + usbPid); } } } |
然后继续调试。
然后的确可以运行到这个run函数了。
12.但是又有问题:
代码:
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 | @Override public void run() { //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 //Toast.makeText(getApplicationContext(), "Begin check usb action", 1000).show(); gLogger.debug( "Begin check usb action" ); 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(); //Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity ", Toast.LENGTH_LONG).show(); gLogger.debug( "Found Usb device: FT232R UART" ); gLogger.debug( "Now send message USB_ACTION_ATTACH to activit" ); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); break ; } else { //Toast.makeText(getApplicationContext(), "Found USB VID="+usbVid+" PID=" + usbPid, Toast.LENGTH_LONG).show(); gLogger.debug( "Found USB VID=" +usbVid+ " PID=" + usbPid); } } try { Thread.sleep( 200 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } |
只运行了一次,只执行了一次的sleep的200毫秒后,结果就不再执行了。
所以需要去解决:
【已解决】为何android中实现了Runnable的进程只运行了一次
然后就可以正常检测usb的状态了。
【总结】
此处,相关代码为:
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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | public class DeviceListActivity extends BaseActivity implements Runnable { private Thread usbActionDetectThread = null ; public Handler mHandler; @Override public void run() { // set to lower priority android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); //0x0403 / 0x6001: FTDI FT232R UART final int ft232rUartVid = 0x0403 ; //1027 final int ft232rUartPid = 0x6001 ; //24577 boolean bNotFoundUsb = true ; while (bNotFoundUsb) { //Toast.makeText(getApplicationContext(), "Begin check usb action", 1000).show(); gLogger.debug( "Begin check usb action" ); 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(); //Toast.makeText(getApplicationContext(), "Now send message USB_ACTION_ATTACH to activity ", Toast.LENGTH_LONG).show(); gLogger.debug( "Found Usb device: FT232R UART" ); gLogger.debug( "Now send message USB_ACTION_ATTACH to activit" ); Message foundUsbDeviceAttachMsg = new Message(); foundUsbDeviceAttachMsg.what=usb_action.USB_ACTION_ATTACH.getAction(); mHandler.sendMessage(foundUsbDeviceAttachMsg); bNotFoundUsb = false ; break ; } else { //Toast.makeText(getApplicationContext(), "Found USB VID="+usbVid+" PID=" + usbPid, Toast.LENGTH_LONG).show(); gLogger.debug( "Found USB VID=" +usbVid+ " PID=" + usbPid); } } //while(deviceIterator.hasNext()){ if (bNotFoundUsb) { try { int sleepTimeInMs = 200 ; gLogger.debug( "Sleep milliseconds: " + sleepTimeInMs); Thread.sleep(sleepTimeInMs); } catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); } } } //while(bNotFoundUsb) } //public void run() } public enum usb_action{ USB_ACTION_UNKNOWN( 0 ), USB_ACTION_ATTACH( 1 ), USB_ACTION_DETACH( 2 ); usb_action ( int action) { this .action = action; } private final int action; public int getAction() { return action; } } private void usbActionDetectViaHandler(){ mHandler= new Handler() { public void handleMessage(Message msg) { usb_action curUsbAction = usb_action.values()[msg.what]; //do your own bounds checking switch (curUsbAction) { case USB_ACTION_UNKNOWN: Toast.makeText(getApplicationContext(), "Unkown USB action !" , Toast.LENGTH_LONG).show(); break ; case USB_ACTION_ATTACH: //TODO: do auto scan hart devices Toast.makeText(getApplicationContext(), "Now should call the HART auto scan" , Toast.LENGTH_LONG).show(); break ; case USB_ACTION_DETACH: //stop auto detect usb action thread Toast.makeText(getApplicationContext(), "Now destory the usb action detect thread" , Toast.LENGTH_LONG).show(); usbActionDetectThread.destroy(); usbActionDetectThread = null ; break ; default : break ; } super .handleMessage(msg); } }; Thread curThread= new Thread( this ); curThread.start(); } private void detectUsbDeviceAttach(){ //Method1: this should work, but due to android usb manager bug: //can not get intert usb attach action //so here can not use this method //usbActionDetectViaFilter(); //Method2: use thread + handler to do usb detect usbActionDetectViaHandler(); } @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); //... detectUsbDeviceAttach(); } @SuppressWarnings ( "deprecation" ) @Override public void onDestroy() { //... super .onDestroy(); //usbOnDestroy(); //TODO: release current resources? thread? ... if ( null != usbActionDetectThread){ if (usbActionDetectThread.isAlive()){ usbActionDetectThread.destroy(); } } } } |
可以实现:
循环执行,检测usb的插入
发送都应的message给handler去处理。
然后后续就可以去执行自己要的动作了。