主要是通过系统发广播来获取USB连接的状态,代码很简单
package com.test.socket.usb;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.widget.Toast;
public class USBReceiver extends BroadcastReceiver {
private static final String TAG = "PiCalib usb";
private final Activity ctx;
private final String action;
public static boolean mUsbConnectStatus = false;
public USBReceiver(Activity mainActivity, String action) {
this.ctx = mainActivity;
this.action = action;
}
@Override
public void onReceive(Context context, Intent intent) {
// 这里可以拿到插入的USB设备对象
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
//registerReceiver()
if (this.action.equals(intent.getAction())) {
mUsbConnectStatus = intent.getExtras().getBoolean("connected");
Toast.makeText(ctx,mUsbConnectStatus+",",Toast.LENGTH_SHORT).show();
}
}
}
private final static String ACTION = "android.hardware.usb.action.USB_STATE";
//注册广播!!!注意要activity退出的时候要反注册,我这里偷懒就不写了
private void registerReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION);
registerReceiver(new USBReceiver(this,ACTION), filter);
//这里就能返回实时状态
boolean mUsbConnectstatus = USBReceiver.mUsbConnectStatus;
}
这里有个小问题,我一直理解的是android.hardware.usb.action.USB_STATE这一条广播是在状态切换的时候才会发送广播,当然状态切换一定会发广播,但是在下列场景下,广播依然会发出来:
1、在APP启动前,USB没有连接,APP启动后,注册动态广播,仍然没有连接USB线,这个广播还是会发送一次USB的状态,此时它是false
2、在APP启动前,USB已经连接,APP启动后,注册动态广播,连接USB线,这个广播依然会发送一次USB的状态,此时它是true
就是说不论有没有切换USB的状态,APP启动,注册了动态广播,它一定会发一条广播给app,也就是说你的APP确实是会拿到状态,我猜测是注册动态广播的时候,系统会给你的APP补发一条广播信息,仅仅是猜测,待后续我去验证
接下来是QT程序中监测USB拔插状态
1、头文件引用
#include <QWidget>
#include <windows.h>
#include <QAbstractNativeEventFilter>
#include <dbt.h>
class ClassA: public QWidget
{
Q_OBJECT
public:
explicit ClassA(QWidget *parent = nullptr);
~ClassA();
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
};
2、cpp文件实现
ClassA::ClassA(QWidget *parent) :
QWidget(parent),
ui(new Ui::TabFirmwareDownload)
{
qDebug()<<"ClassA::ClassA+++";
ui->setupUi(this);
RegisterHIVDeviceNotification();
qDebug()<<"TabFirmwareDownload::TabFirmwareDownload ---";
}
//注册消息
bool ClassA::RegisterHIVDeviceNotification()
{
HDEVNOTIFY hDeviceNotify;
/*
*这里注册的设备是 Human Interface Devices (HID) 类
*GUID_DEVINTERFACE_HID = {4D1E55B2-F16F-11CF-88CB-001111000030}
*/
GUID guid_hiv = {0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30};
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
HWND hWnd = (HWND)(this->winId()); //获取当前窗口句柄
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = guid_hiv;
hDeviceNotify = RegisterDeviceNotification (hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
qDebug() << "hDeviceNotify: "<<hDeviceNotify ;
if (NULL == hDeviceNotify)
return false;
else
return true; //注册消息成功
}
bool ClassA::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(eventType);
Q_UNUSED(result);
MSG* msg = reinterpret_cast<MSG*>(message);
// qDebug() << "msg: "<<msg ;
int msgType = msg->message;
if(msgType == WM_DEVICECHANGE){
switch(msg->wParam){
case DBT_DEVICEARRIVAL:
qDebug() << "插入 " ;
break;
case DBT_DEVICEREMOVECOMPLETE:
qDebug() << "拔出 " ;
break;
}
}
return false;
}
这样就能在运行这个类后,usb拔插实时返回状态了,但是有一个问题,如果你的USB线先连接,再运行程序,这里是无法返回状态的!!!就得想其他办法了,例如程序运行,直接去尝试打开设备节点,