在Qt6 Android环境中申请USB权限并检测Hack-RF设备
Qt6 Android下Hack-RF USB权限申请与设备检测实现方案
核心说明
USB设备权限和Android普通危险权限(如存储)的申请逻辑完全不同,不能用QtAndroidPrivate::requestPermission直接申请。USB权限需要通过Android原生UsbManager发起请求,依赖广播接收器接收授权结果,同时必须在Manifest中声明目标USB设备的过滤规则。
第一步:完善AndroidManifest.xml配置
除你已添加的权限,还需补充USB设备过滤规则和权限广播配置:
<!-- 已有的基础权限与硬件声明 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-feature android:name="android.hardware.usb.host" android:required="true"/> <!-- 自定义USB权限广播Action,替换为你的应用包名 --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <action android:name="com.your.package.USB_PERMISSION"/> <!-- 关联USB设备过滤规则文件 --> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usb_device_filter"/>
在res/xml目录下创建usb_device_filter.xml,匹配Hack-RF的硬件ID:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Hack-RF标准VID=0x1d50(十进制7504),PID=0x6089(十进制24713) --> <usb-device vendor-id="7504" product-id="24713"/> </resources>
第二步:Qt C++层实现设备检测与权限申请
Qt未直接封装USB权限请求API,需通过JNI调用Android原生接口实现。以下是完整可复用的工具类:
1. 头文件(UsbPermissionHelper.h)
#ifndef USBPERMISSIONHELPER_H #define USBPERMISSIONHELPER_H #include <QObject> #include <QtAndroid> #include <QDebug> class UsbPermissionHelper : public QObject { Q_OBJECT public: explicit UsbPermissionHelper(QObject *parent = nullptr); // 检测并申请Hack-RF权限 Q_INVOKABLE bool requestHackRfPermission(); signals: // 权限结果通知信号(可绑定到QML处理) void permissionGranted(bool granted); private slots: // 处理USB权限广播回调 void onUsbPermissionResult(const QAndroidJniObject &intent); private: QAndroidJniObject m_usbManager; const QString USB_PERMISSION_ACTION = "com.your.package.USB_PERMISSION"; // 与Manifest保持一致 const int HACKRF_VID = 0x1d50; const int HACKRF_PID = 0x6089; }; #endif // USBPERMISSIONHELPER_H
2. 实现文件(UsbPermissionHelper.cpp)
#include "UsbPermissionHelper.h" #include <QAndroidIntent> UsbPermissionHelper::UsbPermissionHelper(QObject *parent) : QObject(parent) { // 获取Android系统UsbManager实例 m_usbManager = QAndroidJniObject::callStaticObjectMethod( "android/hardware/usb/UsbManager", "getInstance", "(Landroid/content/Context;)Landroid/hardware/usb/UsbManager;", QtAndroid::androidContext().object()); // 动态注册USB权限广播接收器 QAndroidJniObject action = QAndroidJniObject::fromString(USB_PERMISSION_ACTION); QtAndroid::registerBroadcastReceiver(action, this, SLOT(onUsbPermissionResult(QAndroidJniObject))); } bool UsbPermissionHelper::requestHackRfPermission() { if (!m_usbManager.isValid()) { qDebug() << "UsbManager不可用"; return false; } // 遍历所有已连接USB设备 QAndroidJniObject deviceList = m_usbManager.callObjectMethod("getDeviceList", "()Ljava/util/HashMap;"); if (!deviceList.isValid()) { qDebug() << "获取USB设备列表失败"; return false; } QAndroidJniObject iterator = deviceList.callObjectMethod("keySet", "()Ljava/util/Set;") .callObjectMethod("iterator", "()Ljava/util/Iterator;"); QAndroidJniObject hackRfDevice; bool deviceFound = false; while (iterator.callMethod<bool>("hasNext")) { QAndroidJniObject device = iterator.callObjectMethod("next", "()Ljava/lang/Object;") .cast<jobject>("android/hardware/usb/UsbDevice"); int vid = device.callMethod<int>("getVendorId"); int pid = device.callMethod<int>("getProductId"); if (vid == HACKRF_VID && pid == HACKRF_PID) { hackRfDevice = device; deviceFound = true; break; } } if (!deviceFound) { qDebug() << "未检测到Hack-RF设备"; emit permissionGranted(false); return false; } // 检查是否已有权限 bool hasPermission = m_usbManager.callMethod<bool>( "hasPermission", "(Landroid/hardware/usb/UsbDevice;)Z", hackRfDevice.object()); if (hasPermission) { qDebug() << "已拥有Hack-RF权限"; emit permissionGranted(true); return true; } // 发起权限请求 QAndroidIntent permissionIntent(USB_PERMISSION_ACTION); permissionIntent.setFlags(QAndroidIntent::FlagReceiverForeground); m_usbManager.callMethod<void>( "requestPermission", "(Landroid/hardware/usb/UsbDevice;Landroid/content/Intent;)V", hackRfDevice.object(), permissionIntent.handle().object()); return true; } void UsbPermissionHelper::onUsbPermissionResult(const QAndroidJniObject &intent) { QString action = intent.callObjectMethod("getAction", "()Ljava/lang/String;").toString(); if (action != USB_PERMISSION_ACTION) return; bool granted = intent.getField<jboolean>("EXTRA_PERMISSION_GRANTED"); qDebug() << "USB权限授权结果:" << granted; emit permissionGranted(granted); }
第三步:QML层调用与交互
- 在主函数中注册工具类到QML:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "UsbPermissionHelper.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // 注册工具类到QML命名空间 qmlRegisterType<UsbPermissionHelper>("com.your.package", 1, 0, "UsbPermissionHelper"); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
- QML中调用权限申请:
import QtQuick 2.15 import QtQuick.Window 2.15 import com.your.package 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Hack-RF USB权限测试") UsbPermissionHelper { id: usbHelper onPermissionGranted: { if (granted) { console.log("Hack-RF权限已获取,可开始操作设备") // 此处添加设备操作逻辑 } else { console.log("Hack-RF权限被拒绝") } } } Button { text: "检测并申请Hack-RF权限" anchors.centerIn: parent onClicked: usbHelper.requestHackRfPermission() } }
关键注意事项
- 替换所有
com.your.package为你的实际应用包名,确保Manifest、C++、QML中的包名完全一致。 - 确保Android设备开启OTG功能(部分设备需手动开启),支持USB Host模式。
- 若使用不同版本的Hack-RF,需核对并调整
usb_device_filter.xml中的PID值。
内容的提问来源于stack exchange,提问作者Nemo
相关产品推荐
相关产品推荐

