最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

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

Android crifan 3575浏览 0评论

【背景】

折腾:

【已解决】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.然后用了代码:

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

结果却会出错:

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

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

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

转载请注明:在路上 » 【记录】Android中创建进程或线程去实现USB设备插入的状态检测

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
83 queries in 0.388 seconds, using 22.31MB memory