You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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层调用与交互

  1. 在主函数中注册工具类到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();
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:55:02