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

Qt Android目录操作技术咨询:文件存储路径修正与QProcess调用可行性问题

Hey there! Let's tackle your two Qt-on-Android questions one by one:

1. Fixing the Storage Path Issue

The problem here is that hardcoding absolute paths like /storage/emulated/0/Android/data/ doesn't work reliably on Android, thanks to scoped storage (introduced in Android 10) and Qt's path virtualization for Android apps. When you use a hardcoded external path without proper permissions or Qt's standard path utilities, Android redirects the write operation to your app's private internal storage (/data/user/0/org.qtproject.example.NameApp), which is why you're seeing files end up there.

Here's how to fix it:

  • Use Qt's QStandardPaths for platform-safe paths: For Android, QStandardPaths::ExternalDataLocation points directly to your app's dedicated external storage directory: /storage/emulated/0/Android/data/<your_package_name>/files/. This directory is private to your app (no extra permissions needed on Android 11+), and Qt handles all platform-specific path resolution automatically.
  • Never hardcode paths: Absolute paths can vary across devices or Android versions, so always rely on Qt's path utilities.

Example code to build your target zip path:

#include <QStandardPaths>
#include <QDir>

// Get the app's external data directory
QString externalDataPath = QStandardPaths::writableLocation(QStandardPaths::ExternalDataLocation);
// Create the directory if it doesn't exist
QDir().mkpath(externalDataPath);
// Build your target zip path
QString zipPath = externalDataPath + "/cache.zip";

// Now use this path for your QuaZip operations or rename
m_file.rename(zipPath);

If you specifically need to write to /storage/emulated/0/Android/data/ (not your app's subdirectory):

  1. Add the WRITE_EXTERNAL_STORAGE permission to your AndroidManifest.xml (for Android 9 and below).
  2. For Android 10+, add android:requestLegacyExternalStorage="true" to your <application> tag in AndroidManifest.xml to temporarily bypass scoped storage (note this is deprecated in Android 11+—stick to your app's dedicated directory whenever possible).

2. Opening Files on Android (QProcess Isn't the Right Tool)

Unfortunately, QProcess won't work for opening files on Android the way it does on Windows. Android uses an Intent-based system to launch apps that can handle specific file types, rather than directly executing commands like desktop systems.

To open a file, you'll need to use Qt's Android Extras module to call Android's native Intent system. Here's how:

Step 1: Add Qt Android Extras to your project

Add this line to your .pro file:

QT += androidextras

Step 2: Code to open a file using Intent

This example handles Android 7+'s FileProvider requirement (to avoid FileUriExposedException):

#include <QAndroidJniObject>
#include <QAndroidIntent>
#include <QFile>

void openFile(const QString& filePath) {
    QFile file(filePath);
    if (!file.exists()) {
        // Handle file not found error
        return;
    }

    // Convert Qt file path to Android File object
    QAndroidJniObject javaFile = QAndroidJniObject::fromString(filePath);
    QAndroidJniObject fileUri;

    // Use FileProvider for Android 7.0 (API 24) and above
    if (QAndroidJniEnvironment().version() >= JNI_VERSION_1_6 && 
        QAndroidJniObject::callStaticMethod<jint>("android/os/Build$VERSION", "SDK_INT") >= 24) {
        QAndroidJniObject authority = QAndroidJniObject::fromString("org.qtproject.example.NameApp.fileprovider"); // Replace with your package name + .fileprovider
        fileUri = QAndroidJniObject::callStaticObjectMethod("androidx/core/content/FileProvider", "getUriForFile",
                                                            "(Landroid/content/Context;Ljava/lang/String;Ljava/io/File;)Landroid/net/Uri;",
                                                            QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;").object(),
                                                            authority.object(),
                                                            javaFile.object());
    } else {
        // Use file:// URI for older Android versions
        fileUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "fromFile", "(Ljava/io/File;)Landroid/net/Uri;", javaFile.object());
    }

    // Create ACTION_VIEW Intent to open the file
    QAndroidIntent intent(QAndroidJniObject::getStaticObjectField("android/content/Intent", "ACTION_VIEW", "Ljava/lang/String;"));
    intent.setData(fileUri);
    intent.setFlags(QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_READ_URI_PERMISSION"));

    // Launch the Intent
    QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
    activity.callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.handle());
}

Step 3: Configure FileProvider (for Android 7+)

  1. Create res/xml/file_paths.xml in your Android resources directory:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_files" path="."/>
</paths>

This tells FileProvider to share files from your app's external files directory.

  1. Add the FileProvider to your AndroidManifest.xml:
<application ...>
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="org.qtproject.example.NameApp.fileprovider" <!-- Match the authority in your code -->
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>
</application>

Replace org.qtproject.example.NameApp with your actual app's package name.


内容的提问来源于stack exchange,提问作者Ed Vestorn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:54:07