Qt6 Android:如何在Android平台使用Qt应用打开与分享文件
Qt6 Android平台实现文件打开与分享功能
一、文件分享功能实现
针对Qt6适配Android 10+分区存储和权限规则,直接通过JNI调用Android原生API是最可靠的方案:
准备可共享的文件
- 将文件存放在应用私有外部存储路径,可通过
QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)获取该路径,避免权限限制。 - 若需分享公共目录文件,建议通过系统文件选择器获取文件Uri,而非直接操作绝对路径。
- 将文件存放在应用私有外部存储路径,可通过
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>()); } }配置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:
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"); }权限适配注意
- Android 13+访问公共媒体文件,需申请
READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO权限;若使用系统文件选择器(Intent.ACTION_OPEN_DOCUMENT)获取Uri,则无需申请这些权限。 - 应用私有文件仅需通过FileProvider共享,无需额外权限。
- Android 13+访问公共媒体文件,需申请
三、Qt6适配核心要点
- 废弃旧版
QtAndroid类,统一使用QAndroidJniObject/QAndroidJniEnvironment进行JNI交互。 - 强制适配AndroidX,Qt6 Android构建套件默认集成,无需额外配置。
- 遵循Android分区存储规则,避免直接操作公共目录绝对路径,优先使用ContentProvider或系统文件选择器。
内容的提问来源于stack exchange,提问作者Mohsen Kondori
相关产品推荐
相关产品推荐

