Programatically iterate over public Files in Android
-
I want to read several public folders on a Android SDK34 device and use the content to build a app internal DB. Examples are the DCIM folder, Documents or Downloads. Which non interactive Qt file access APIs might help with that task?
The Qt-6.11.1 Application has in CMakeLists.txt following permissions:
QT_ADD_ANDROID_PERMISSION( ${PROJECT_NAME}
NAME android.permission.READ_INTERNAL_STORAGE
android.permission.WRITE_INTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_MEDIA_IMAGES
android.permission.READ_MEDIA_AUDIO
android.permission.READ_MEDIA_VIDEO
android.permission.INTERNET
)The QML FileDialog, which is not programatical, does see all files very nicely. It probably uses SAF or MediaStorage according to a post from 2023. What is the current stage of support. Which API allows to use that in a programatic way?
For the record: QStandardPaths::standardLocations(type) returns only app specific paths.
Before the QML FileDialog I tried without much luck:
The old Android QtAndroidPrivate::requestPermissions() are gone. Even though it is mentionened in the private header file
<QtCore/private/qandroidextras_p.h>, this symbol is not resolved by the linker on arm64-v8a using Qt Creator 20.0.0 (RH Linux)
/opt/android-sdk/ndk/27.2.12479018/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android32
ld.lld: error: undefined symbol: requestPermissionsInternal(QList<QString> const&) -
I want to read several public folders on a Android SDK34 device and use the content to build a app internal DB. Examples are the DCIM folder, Documents or Downloads. Which non interactive Qt file access APIs might help with that task?
The Qt-6.11.1 Application has in CMakeLists.txt following permissions:
QT_ADD_ANDROID_PERMISSION( ${PROJECT_NAME}
NAME android.permission.READ_INTERNAL_STORAGE
android.permission.WRITE_INTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_MEDIA_IMAGES
android.permission.READ_MEDIA_AUDIO
android.permission.READ_MEDIA_VIDEO
android.permission.INTERNET
)The QML FileDialog, which is not programatical, does see all files very nicely. It probably uses SAF or MediaStorage according to a post from 2023. What is the current stage of support. Which API allows to use that in a programatic way?
For the record: QStandardPaths::standardLocations(type) returns only app specific paths.
Before the QML FileDialog I tried without much luck:
The old Android QtAndroidPrivate::requestPermissions() are gone. Even though it is mentionened in the private header file
<QtCore/private/qandroidextras_p.h>, this symbol is not resolved by the linker on arm64-v8a using Qt Creator 20.0.0 (RH Linux)
/opt/android-sdk/ndk/27.2.12479018/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android32
ld.lld: error: undefined symbol: requestPermissionsInternal(QList<QString> const&)@beku2 On C++ side you can use https://doc.qt.io/qt-6/qdiriterator.html to iterate over files/folders.
-
The flow in my app is like:
Android SDK 34 -> QML-> check permission -> if not: show reason why as text and ask for agreement -> requestPermission() (now copied from Qt sources into my app_data.cpp)debug output in QtCreator:
I/app_data.cpp:506 requestPermissionsInternal(): after AndroidDeadlockProtector
I/app_data.cpp:513 requestPermissionsInternal(): after promise->start()
I/app_data.cpp:476 nextRequestCode(): code:225
I/app_data.cpp:519 requestPermissionsInternal(): after locker.unlock()
I/app_data.cpp:529 operator()(): perm:android.permission.MANAGE_EXTERNAL_STORAGE
I/app_data.cpp:543 requestPermissionsInternal(): after releaseAndroidDeadlockProtector
I/app_data.cpp:632 requestPermissions(): after oyjlArgsQmlRequestPermissions(android.permission.MANAGE_EXTERNAL_STORAGE)
I/app_data.cpp:537 operator()(): after activity().callMethod requestCode:225
W/default : Found no valid pending permission request for request code 225... the app is keeps frozen after (QFuture result; ...) result.waitForFinished();
-
Give up the extensive MANAGE_EXTERNAL_STORAGE permission (which is stuck because it doesn't have proper callback wiring in Qt) and instead use SAF (ACTION_OPEN_DOCUMENT_TREE with takePersistableUriPermission) for one-time folder selection, or the MediaStore API if it's just media files.