【背景】
折腾:
【已解决】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.然后用了代码:
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();
}结果却会出错:
参考:
[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去处理。
然后后续就可以去执行自己要的动作了。