【记录】Android中创建进程或线程去实现USB设备插入的状态检测

【背景】

折腾:

【已解决】Android设备作为Host希望实现可以检测到USB设备插入

期间,需要尝试去通过,新建一个线程或进程,然后去动态检测USB设备的插入。

【折腾过程】

1.先去搞懂,android中如何新建线程。

2.官网文档:

https://developer.android.com/reference/java/lang/Thread.html

3.看看:

Android 线程 thread 两种实现方法!

Android create new thread in service class

去试试。

4.期间出现:

【已解决】android中switch中的case中不用使用enum枚举值:Type mismatch: cannot convert from xxx to int

5.再去继续写代码测试。

然后又遇到:

【已解决】android中enum转换为int

6.然后用了代码:

		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

去改为:

		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:

//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();
    }

结果却会出错:

jdi thread evaluations exception processing async thread queue

参考:

[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.后来发现,上述代码出错了:

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)

看代码中的:

public void run() {

很明显是:

第一句就是:

298行的:

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算了:

	@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.但是又有问题:

代码:

	@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的状态了。

 

【总结】

此处,相关代码为:

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去处理。

然后后续就可以去执行自己要的动作了。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量