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

Qt6 Android:如何在Android平台使用Qt应用打开与分享文件

Qt6 Android平台实现文件打开与分享功能

一、文件分享功能实现

针对Qt6适配Android 10+分区存储和权限规则,直接通过JNI调用Android原生API是最可靠的方案:

  1. 准备可共享的文件

    • 将文件存放在应用私有外部存储路径,可通过QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)获取该路径,避免权限限制。
    • 若需分享公共目录文件,建议通过系统文件选择器获取文件Uri,而非直接操作绝对路径。
  2. JNI调用原生分享逻辑
    编写C++代码调用Android的Intent.ACTION_SEND发起分享:

    #include <QAndroidJniObject>
    #include <QAndroidJniEnvironment>
    #include <QFileInfo>
    
    void shareFile(const QString &filePath) {
        QAndroidJniObject javaFile = QAndroidJniObject::fromString(filePath);
        QAndroidJniObject file("java/io/File", "(Ljava/lang/String;)V", javaFile.object<jstring>());
        QAndroidJniObject context = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt/android/QtNative", "activity", "()Landroid/app/Activity;");
    
        if (context.isValid() && file.callMethod<jboolean>("exists")) {
            // 获取文件Uri(依赖FileProvider)
            QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
                "androidx/core/content/FileProvider", "getUriForFile",
                "(Landroid/content/Context;Ljava/lang/String;Ljava/io/File;)Landroid/net/Uri;",
                context.object<jobject>(),
                QAndroidJniObject::fromString("com.your.app.id.fileprovider").object<jstring>(),
                file.object<jobject>()
            );
    
            // 创建分享Intent
            QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", 
                                     QAndroidJniObject::fromString("android.intent.action.SEND").object<jstring>());
            intent.callObjectMethod("putExtra", "(Ljava/lang/String;Landroid/net/Uri;)Landroid/content/Intent;",
                                    QAndroidJniObject::fromString("android.intent.extra.STREAM").object<jstring>(),
                                    uri.object<jobject>());
    
            // 设置MIME类型
            QString suffix = QFileInfo(filePath).suffix().toLower();
            QAndroidJniObject mimeType = QAndroidJniObject::callStaticObjectMethod(
                "android/webkit/MimeTypeMap", "getSingleton", "()Landroid/webkit/MimeTypeMap;"
            )->callObjectMethod("getMimeTypeFromExtension", "(Ljava/lang/String;)Ljava/lang/String;",
                               QAndroidJniObject::fromString(suffix).object<jstring>());
            intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", 
                                   mimeType.isValid() ? mimeType.object<jstring>() : QAndroidJniObject::fromString("application/octet-stream").object<jstring>());
    
            // 显示分享选择器
            QAndroidJniObject chooser = QAndroidJniObject::callStaticObjectMethod(
                "android/content/Intent", "createChooser",
                "(Landroid/content/Intent;Ljava/lang/String;)Landroid/content/Intent;",
                intent.object<jobject>(),
                QAndroidJniObject::fromString("分享文件").object<jstring>()
            );
            context.callMethod<void>("startActivity", "(Landroid/content/Intent;)V", chooser.object<jobject>());
        }
    }
    
  3. 配置FileProvider(关键)

    • 在AndroidManifest.xml中添加Provider配置:
      <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="com.your.app.id.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
              android:name="android.support.FILE_PROVIDER_PATHS"
              android:resource="@xml/file_paths" />
      </provider>
      
    • 在res/xml目录下创建file_paths.xml,指定共享路径:
      <?xml version="1.0" encoding="utf-8"?>
      <paths>
          <external-files-path name="external_files" path="." />
      </paths>
      
    • 替换com.your.app.id为你的应用包名,Qt6默认支持AndroidX,无需额外依赖。

二、文件打开功能实现

调用其他应用打开文件的逻辑与分享类似,仅需修改Intent的Action:

  1. JNI调用原生打开逻辑

    void openFile(const QString &filePath) {
        QAndroidJniObject javaFile = QAndroidJniObject::fromString(filePath);
        QAndroidJniObject file("java/io/File", "(Ljava/lang/String;)V", javaFile.object<jstring>());
        QAndroidJniObject context = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt/android/QtNative", "activity", "()Landroid/app/Activity;");
    
        if (context.isValid() && file.callMethod<jboolean>("exists")) {
            QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
                "androidx/core/content/FileProvider", "getUriForFile",
                "(Landroid/content/Context;Ljava/lang/String;Ljava/io/File;)Landroid/net/Uri;",
                context.object<jobject>(),
                QAndroidJniObject::fromString("com.your.app.id.fileprovider").object<jstring>(),
                file.object<jobject>()
            );
    
            // 创建打开文件的Intent
            QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", 
                                     QAndroidJniObject::fromString("android.intent.action.VIEW").object<jstring>());
            intent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;",
                                    uri.object<jobject>(),
                                    getMimeType(filePath).object<jstring>());
            intent.callObjectMethod("addFlags", "(I)Landroid/content/Intent;", 0x00000001); // 授予Uri读取权限
    
            // 显示打开选择器
            QAndroidJniObject chooser = QAndroidJniObject::callStaticObjectMethod(
                "android/content/Intent", "createChooser",
                "(Landroid/content/Intent;Ljava/lang/String;)Landroid/content/Intent;",
                intent.object<jobject>(),
                QAndroidJniObject::fromString("打开文件").object<jstring>()
            );
            context.callMethod<void>("startActivity", "(Landroid/content/Intent;)V", chooser.object<jobject>());
        }
    }
    
    // 辅助函数:获取文件MIME类型
    QAndroidJniObject getMimeType(const QString &filePath) {
        QString suffix = QFileInfo(filePath).suffix().toLower();
        QAndroidJniObject mimeType = QAndroidJniObject::callStaticObjectMethod(
            "android/webkit/MimeTypeMap", "getSingleton", "()Landroid/webkit/MimeTypeMap;"
        )->callObjectMethod("getMimeTypeFromExtension", "(Ljava/lang/String;)Ljava/lang/String;",
                           QAndroidJniObject::fromString(suffix).object<jstring>());
        return mimeType.isValid() ? mimeType : QAndroidJniObject::fromString("application/octet-stream");
    }
    
  2. 权限适配注意

    • Android 13+访问公共媒体文件,需申请READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO权限;若使用系统文件选择器(Intent.ACTION_OPEN_DOCUMENT)获取Uri,则无需申请这些权限。
    • 应用私有文件仅需通过FileProvider共享,无需额外权限。

三、Qt6适配核心要点

  • 废弃旧版QtAndroid类,统一使用QAndroidJniObject/QAndroidJniEnvironment进行JNI交互。
  • 强制适配AndroidX,Qt6 Android构建套件默认集成,无需额外配置。
  • 遵循Android分区存储规则,避免直接操作公共目录绝对路径,优先使用ContentProvider或系统文件选择器。

内容的提问来源于stack exchange,提问作者Mohsen Kondori

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:35:05