123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 | // Copyright (C) 2023 The Qt Company Ltd.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#include"qstandardpaths.h"#ifndef QT_NO_STANDARDPATHS#include <QtCore/qjniobject.h>#include <QtCore/qmap.h>#include <QtCore/qcoreapplication.h>#include <QDir> QT_BEGIN_NAMESPACE Q_DECLARE_JNI_CLASS(Environment,"android/os/Environment");using namespace QNativeInterface;using namespaceQt::StringLiterals;typedef QMap<QString, QString> AndroidDirCache;Q_GLOBAL_STATIC(AndroidDirCache, androidDirCache)static QString testDir(){returnQStandardPaths::isTestModeEnabled() ?"/qttest"_L1 :""_L1;}staticinline QString getAbsolutePath(const QJniObject &file){ QJniObject path = file.callMethod<jstring>("getAbsolutePath");if(!path.isValid())returnQString();return path.toString();}/* * The root of the external storage * */static QString getExternalStorageDirectory(){ QString &path = (*androidDirCache)[QStringLiteral("EXT_ROOT")];if(!path.isEmpty())return path; QJniObject file =QJniObject::callStaticMethod<QtJniTypes::File>("android/os/Environment","getExternalStorageDirectory");if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}/* * Locations where applications can place user files shared by all apps (public). * E.g., /storage/Music */static QString getExternalStoragePublicDirectory(const char*directoryField){ QString &path = (*androidDirCache)[QLatin1String(directoryField)];if(!path.isEmpty())return path; QJniObject dirField =QJniObject::getStaticField<jstring>("android/os/Environment", directoryField);if(!dirField.isValid())returnQString(); QJniObject file =QJniObject::callStaticMethod<QtJniTypes::File>("android/os/Environment","getExternalStoragePublicDirectory", dirField.object<jstring>());if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}/* * Locations where applications can place persistent files it owns. * E.g., /storage/org.app/Music */static QString getExternalFilesDir(const char*directoryField =nullptr){ QString &path = (*androidDirCache)["APPNAME_%1"_L1.arg(QLatin1StringView(directoryField))];if(!path.isEmpty())return path; QJniObject appCtx =QAndroidApplication::context();if(!appCtx.isValid())returnQString(); QJniObject dirField =QJniObject::fromString(""_L1);if(directoryField &&strlen(directoryField) >0) { dirField =QJniObject::getStaticField<QtJniTypes::Environment, jstring>(directoryField);if(!dirField.isValid())returnQString();} QJniObject file = appCtx.callMethod<QtJniTypes::File>("getExternalFilesDir", dirField.object<jstring>());if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}/* * Directory where applications can store cache files it owns (public). * E.g., /storage/org.app/ */static QString getExternalCacheDir(){ QString &path = (*androidDirCache)[QStringLiteral("APPNAME_CACHE")];if(!path.isEmpty())return path; QJniObject appCtx =QAndroidApplication::context();if(!appCtx.isValid())returnQString(); QJniObject file = appCtx.callMethod<QtJniTypes::File>("getExternalCacheDir");if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}/* * Directory where applications can store cache files it owns (private). */static QString getCacheDir(){ QString &path = (*androidDirCache)[QStringLiteral("APPROOT_CACHE")];if(!path.isEmpty())return path; QJniObject appCtx =QAndroidApplication::context();if(!appCtx.isValid())returnQString(); QJniObject file = appCtx.callMethod<QtJniTypes::File>("getCacheDir");if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}/* * Directory where applications can store files it owns (private). * (Same location as $HOME) */static QString getFilesDir(){ QString &path = (*androidDirCache)[QStringLiteral("APPROOT_FILES")];if(!path.isEmpty())return path; QJniObject appCtx =QAndroidApplication::context();if(!appCtx.isValid())returnQString(); QJniObject file = appCtx.callMethod<QtJniTypes::File>("getFilesDir");if(!file.isValid())returnQString();return(path =getAbsolutePath(file));}static QString getSdkBasedExternalDir(const char*directoryField =nullptr){return(QNativeInterface::QAndroidApplication::sdkVersion() >=30)?getExternalFilesDir(directoryField):getExternalStoragePublicDirectory(directoryField);} QString QStandardPaths::writableLocation(StandardLocation type){switch(type) {caseQStandardPaths::MusicLocation:returngetSdkBasedExternalDir("DIRECTORY_MUSIC");caseQStandardPaths::MoviesLocation:returngetSdkBasedExternalDir("DIRECTORY_MOVIES");caseQStandardPaths::PicturesLocation:returngetSdkBasedExternalDir("DIRECTORY_PICTURES");caseQStandardPaths::DocumentsLocation:returngetSdkBasedExternalDir("DIRECTORY_DOCUMENTS");caseQStandardPaths::DownloadLocation:returngetSdkBasedExternalDir("DIRECTORY_DOWNLOADS");caseQStandardPaths::GenericConfigLocation:caseQStandardPaths::ConfigLocation:caseQStandardPaths::AppConfigLocation:returngetFilesDir() +testDir() +"/settings"_L1;caseQStandardPaths::StateLocation:caseQStandardPaths::GenericStateLocation:returngetFilesDir() +testDir() +"/state"_L1;caseQStandardPaths::GenericDataLocation:{returnQAndroidApplication::sdkVersion() >=30?getExternalFilesDir() +testDir() :getExternalStorageDirectory() +testDir();}caseQStandardPaths::AppDataLocation:caseQStandardPaths::AppLocalDataLocation:returngetFilesDir() +testDir();caseQStandardPaths::GenericCacheLocation:caseQStandardPaths::RuntimeLocation:caseQStandardPaths::TempLocation:caseQStandardPaths::CacheLocation:returngetCacheDir() +testDir();caseQStandardPaths::DesktopLocation:caseQStandardPaths::HomeLocation:returngetFilesDir();caseQStandardPaths::ApplicationsLocation:caseQStandardPaths::FontsLocation:caseQStandardPaths::PublicShareLocation:caseQStandardPaths::TemplatesLocation:default:break;}returnQString();} QStringList QStandardPaths::standardLocations(StandardLocation type){ QStringList locations;if(type == MusicLocation) { locations <<getExternalFilesDir("DIRECTORY_MUSIC");// Place the public dirs before the app own dirsif(QNativeInterface::QAndroidApplication::sdkVersion() <30) { locations <<getExternalStoragePublicDirectory("DIRECTORY_PODCASTS")<<getExternalStoragePublicDirectory("DIRECTORY_NOTIFICATIONS")<<getExternalStoragePublicDirectory("DIRECTORY_ALARMS");} locations <<getExternalFilesDir("DIRECTORY_PODCASTS")<<getExternalFilesDir("DIRECTORY_NOTIFICATIONS")<<getExternalFilesDir("DIRECTORY_ALARMS");}else if(type == MoviesLocation) { locations <<getExternalFilesDir("DIRECTORY_MOVIES");}else if(type == PicturesLocation) { locations <<getExternalFilesDir("DIRECTORY_PICTURES");}else if(type == DocumentsLocation) { locations <<getExternalFilesDir("DIRECTORY_DOCUMENTS");}else if(type == DownloadLocation) { locations <<getExternalFilesDir("DIRECTORY_DOWNLOADS");}else if(type == AppDataLocation || type == AppLocalDataLocation) { locations <<getExternalFilesDir();}else if(type == CacheLocation) { locations <<getExternalCacheDir();}else if(type == FontsLocation) { QString &fontLocation = (*androidDirCache)[QStringLiteral("FONT_LOCATION")];if(!fontLocation.isEmpty()) { locations << fontLocation;}else{const QByteArray ba =qgetenv("QT_ANDROID_FONT_LOCATION");if(!ba.isEmpty()) { locations << (fontLocation =QDir::cleanPath(QString::fromLocal8Bit(ba)));}else{// Don't cache the fallback, as we might just have been called before// QT_ANDROID_FONT_LOCATION has been set. locations <<"/system/fonts"_L1;}}}const QString writable =writableLocation(type);if(!writable.isEmpty()) locations.prepend(writable); locations.removeDuplicates();return locations;} QT_END_NAMESPACE #endif// QT_NO_STANDARDPATHS
|