Доступ ко всем файлам android QT
Мне надо отобразить всю файловую систему android /storage/emulated/0, но моему приложению можно получить доступ только к мультимедиа, из за этого при отображении файлов в какой либо папке у меня отображаются только медиафайлы Как мне получить доступ ко всей файловой системе как это делают файловые менеджеры?
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "filemanager.h"
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#ifdef Q_OS_ANDROID
#include <QJniObject>
#include <QJniEnvironment>
#endif
void requestPermissions() {
#ifdef Q_OS_ANDROID
QJniObject activity = QJniObject::callStaticObjectMethod(
"org/qtproject/qt/android/QtNative",
"activity",
"()Landroid/app/Activity;"
);
if (activity.isValid()) {
QJniEnvironment env;
jobjectArray permissions = env->NewObjectArray(1, env->FindClass("java/lang/String"), nullptr);
env->SetObjectArrayElement(permissions, 0, QJniObject::fromString("android.permission.READ_EXTERNAL_STORAGE").object());
QJniObject::callStaticMethod<void>(
"androidx/core/app/ActivityCompat",
"requestPermissions",
"(Landroid/app/Activity;[Ljava/lang/String;I)V",
activity.object(),
permissions,
1
);
env->DeleteLocalRef(permissions); // Освобождаем память
}
#endif
}
void listFiles(const QString &path) {
QDir dir(path);
if (!dir.exists()) {
qWarning() << "Directory doesn't exist:" << path;
return;
}
// Получаем список всех файлов и директорий в текущем каталоге
QStringList entries = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
qDebug() << "Files and directories in" << path << ":";
for (const QString &entry : entries) {
QFileInfo fileInfo(dir.filePath(entry));
if (fileInfo.isDir()) {
qDebug() << "Directory:" << fileInfo.absoluteFilePath();
} else {
qDebug() << "File:" << fileInfo.absoluteFilePath();
}
}
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//requestPermissions();
listFiles("/storage/emulated/0");
FileManager fileManager;
engine.rootContext()->setContextProperty("fileManager", &fileManager);
engine.loadFromModule("MobileUI", "Main");
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
#include "main.moc"
filemanager.h
#ifndef FILEMANAGER_H
#define FILEMANAGER_H
#include <QObject>
#include <QStringList>
#include <QDir>
#include <QFileInfo>
#include <QVariantList>
#include <QDebug>
class FileManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList items READ items NOTIFY itemsChanged)
Q_PROPERTY(QStringList selectedFiles READ selectedFiles WRITE setSelectedFiles NOTIFY selectedFilesChanged)
Q_PROPERTY(QString currentPath READ currentPath NOTIFY currentPathChanged)
public:
explicit FileManager(QObject *parent = nullptr) : QObject(parent) {
m_currentPath = QDir::homePath();
}
QVariantList items() const { return m_items; }
QStringList selectedFiles() const { return m_selectedFiles; }
QString currentPath() const { return m_currentPath; }
void setSelectedFiles(const QStringList &files) {
if (m_selectedFiles != files) {
m_selectedFiles = files;
emit selectedFilesChanged();
}
}
Q_INVOKABLE void listFiles(const QString &path) {
QDir dir(path);
if (!dir.exists()) {
emit errorOccurred("Directory doesn't exist: " + path);
return;
}
m_currentPath = dir.absolutePath();
m_items.clear();
// Добавляем все файлы и папки, включая скрытые
QStringList entries = dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
for (const QString &entry : entries) {
QFileInfo fileInfo(dir.filePath(entry));
QVariantMap item;
item["name"] = fileInfo.fileName();
item["isDirectory"] = fileInfo.isDir();
m_items.append(item);
}
emit itemsChanged();
emit currentPathChanged();
}
Q_INVOKABLE void goUp() {
QDir dir(m_currentPath);
if (dir.cdUp()) {
listFiles(dir.absolutePath());
}
}
Q_INVOKABLE void toggleFileSelection(const QString &fileName) {
QString fullPath = m_currentPath + "/" + fileName;
if (m_selectedFiles.contains(fullPath)) {
m_selectedFiles.removeAll(fullPath);
} else {
m_selectedFiles.append(fullPath);
}
}
Q_INVOKABLE void updateSelectedFiles() {
qDebug() << "Выбранные файлы:";
for (const QString &file : m_selectedFiles) {
qDebug() << file;
}
emit selectedFilesChanged();
}
signals:
void itemsChanged();
void selectedFilesChanged();
void currentPathChanged();
void errorOccurred(const QString &message);
private:
QVariantList m_items;
QStringList m_selectedFiles;
QString m_currentPath;
};
#endif // FILEMANAGER_H
androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.qtproject.MobileUI" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
<!-- Разрешения -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Уведомление о том, что приложение может запросить доступ к управлению файлами -->
<queries>
<intent>
<action android:name="android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION"/>
</intent>
</queries>
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:hardwareAccelerated="true" android:label="NetShare" android:allowBackup="true" android:fullBackupOnly="false" android:hasFragileUserData="true">
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:launchMode="singleTop" android:screenOrientation="unspecified" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="Qt6Lib"/>
<meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/>
</activity>
<!-- FileProvider для работы с файлами -->
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.qtprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/qtprovider_paths"/>
</provider>
</application>
</manifest>
main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 600
title: "File Manager"
Column {
anchors.fill: parent
spacing: 10
Rectangle {
width: parent.width
height: 50
color: "#eeeeee"
border.color: "gray"
Row {
spacing: 10
anchors.centerIn: parent
Button {
text: "⬆ Назад"
enabled: fileManager.currentPath !== "/"
onClicked: fileManager.goUp()
}
Text {
text: fileManager.currentPath
font.bold: true
}
}
}
ListView {
width: parent.width
height: 500
model: fileManager.items
delegate: Item {
width: parent.width
height: 40
Rectangle {
width: parent.width
height: 40
color: "#f0f0f0"
border.color: "black"
Row {
spacing: 10
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
Text {
text: modelData.isDirectory ? "? " + modelData.name : "? " + modelData.name
font.bold: modelData.isDirectory
}
}
CheckBox {
id: fileCheckBox
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10
visible: !modelData.isDirectory
checked: fileManager.selectedFiles.includes(fileManager.currentPath + "/" + modelData.name)
onClicked: fileManager.toggleFileSelection(modelData.name)
}
MouseArea {
anchors.fill: parent
onClicked: {
if (modelData.isDirectory) {
fileManager.listFiles(fileManager.currentPath + "/" + modelData.name);
} else {
fileCheckBox.checked = !fileCheckBox.checked;
fileManager.toggleFileSelection(modelData.name);
}
}
}
}
}
}
Button {
text: "Выбранные файлы"
width: parent.width
onClicked: {
fileManager.updateSelectedFiles();
console.log("Выбранные файлы:", fileManager.selectedFiles);
}
}
}
Component.onCompleted: fileManager.listFiles("/storage/emulated/0")
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MobileUI VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#find_package(Qt6 REQUIRED COMPONENTS Quick)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick)
qt_standard_project_setup(REQUIRES 6.5)
qt_add_executable(appMobileUI
main.cpp
)
qt_add_qml_module(appMobileUI
URI MobileUI
VERSION 1.0
QML_FILES
Main.qml
SOURCES FileManager.h
SOURCES filemanager.h filemanager.cpp
RESOURCES android/AndroidManifest.xml android/build.gradle android/res/values/libs.xml android/res/xml/qtprovider_paths.xml android/gradle/wrapper/gradle-wrapper.jar android/gradle/wrapper/gradle-wrapper.properties android/gradle.properties android/gradlew android/gradlew.bat
)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appMobileUI PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appMobileUI
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appMobileUI
PRIVATE Qt6::Core Qt6::Gui Qt6::Quick
)
include(GNUInstallDirs)
install(TARGETS appMobileUI
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)