You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Qt 6.9 Android应用中如何通过USB-OTG访问USB设备?

Qt 6.9 Android应用中如何通过USB-OTG访问USB设备?

我来帮你一步步解决这个问题,核心是要让Android系统识别到你的应用具备处理目标USB设备的能力,同时做好权限和代码层面的适配,具体操作如下:

1. 配置AndroidManifest.xml,让系统识别你的应用

这是让应用出现在“打开方式”列表的关键。你需要在项目的AndroidManifest.xml里添加USB相关的权限、功能声明,以及intent过滤器,告诉系统你的应用能处理USB设备连接事件。

首先添加USB Host权限和功能声明:

<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />

然后在主Activity标签内,添加处理USB设备连接的intent过滤器和元数据(注意和你现有Activity配置合并):

<activity android:name="org.qtproject.qt.android.bindings.QtActivity"
          android:label="@string/app_name">
    <!-- 保留你已有的其他配置 -->
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
               android:resource="@xml/device_filter" />
</activity>

2. 创建USB设备过滤规则文件

上面的配置引用了@xml/device_filter,你需要在项目的res/xml目录下创建这个device_filter.xml文件,用来定义你的应用要匹配的USB设备。可以指定特定厂商ID、产品ID,也可以匹配整个设备类别(比如存储设备、串口设备)。

比如匹配某个特定USB设备:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="1234" product-id="5678" />
</resources>

如果要匹配所有存储类设备(设备类代码为08),可以这样写:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device class="08" />
</resources>

3. 主动申请USB权限(可选但推荐)

有时候系统不会自动弹出权限请求,这时候你需要在应用里主动向系统申请USB设备的访问权限。因为用的是Qt 6.9,得先启用Qt Android Extras模块,在.pro文件里添加:

QT += androidextras

然后在代码中添加权限检查逻辑(通过QAndroidJniObject调用Android原生API):

#include <QAndroidJniObject>
#include <QAndroidIntent>
#include <QDebug>

void checkAndRequestUsbPermission() {
    // 获取Android系统的UsbManager
    QAndroidJniObject usbManager = QAndroidJniObject::callStaticObjectMethod(
        "android/content/Context", "getSystemService",
        "(Ljava/lang/String;)Ljava/lang/Object;",
        QAndroidJniObject::getStaticObjectField("android/content/Context", "USB_SERVICE", "Ljava/lang/String;").object<jstring>()
    );

    // 遍历所有连接的USB设备,这里以第一个设备为例
    QAndroidJniObject deviceList = usbManager.callObjectMethod("getDeviceList", "()Ljava/util/HashMap;");
    QAndroidJniObject entrySet = deviceList.callObjectMethod("entrySet", "()Ljava/util/Set;");
    QAndroidJniObject iterator = entrySet.callObjectMethod("iterator", "()Ljava/util/Iterator;");
    QAndroidJniObject targetDevice;

    if (iterator.callMethod<jboolean>("hasNext")) {
        QAndroidJniObject entry = iterator.callObjectMethod("next", "()Ljava/lang/Object;");
        targetDevice = entry.callObjectMethod("getValue", "()Ljava/lang/Object;");
    }

    if (targetDevice.isValid()) {
        // 检查是否已有设备访问权限
        jboolean hasPermission = usbManager.callMethod<jboolean>("hasPermission",
            "(Landroid/hardware/usb/UsbDevice;)Z", targetDevice.object<jobject>());
        
        if (!hasPermission) {
            // 发送权限请求广播
            QAndroidJniObject permissionAction = QAndroidJniObject::getStaticObjectField(
                "android/hardware/usb/UsbManager", "ACTION_USB_PERMISSION", "Ljava/lang/String;");
            QAndroidIntent permissionIntent(permissionAction.toString());
            QAndroidJniObject appContext = QAndroidJniObject::callStaticObjectMethod(
                "org/qtproject/qt/android/QtNative", "context", "()Landroid/content/Context;");
            
            QAndroidJniObject::callStaticMethod<void>(
                "android/content/Context", "sendBroadcast",
                "(Landroid/content/Intent;)V", permissionIntent.handle().object<jobject>()
            );
        }
    }
}

4. 确保项目资源被正确打包

把你的AndroidManifest.xml和res文件夹放在项目的android子目录下,然后在.pro文件中添加:

ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android

这样Qt编译Android安装包时,会自动包含这些自定义的Android配置文件。

按照这些步骤配置后,当你通过OTG线连接目标USB设备时,你的应用应该会出现在系统的“打开方式”列表里,也能正常访问USB设备的接口了。

内容来源于stack exchange

火山引擎 最新活动