[Interest] Android 13 Devices – API 30+ - SelectFiles – CreateFiles – Qt 5.15

ekke ekke at ekkes-corner.org
Thu Nov 24 18:24:04 CET 2022


as written below I was able to get Content URIs from FileDialog using a 
small test app:
content://com.android.externalstorage.documents/document/primary%3ADocuments%2Fekke.txt

now I wanted to implement this in my customer app. unfortunately now the 
Content URIs from FileDialog look different:
content://com.android.providers.media.documents/document/document%3A1000000020

this URI also gives me access to the file content, but I'm missing the 
name and suffix
any idea what could cause this different behavior ?

same environment, same QML FileDialog from QtQuick.Dialogs1.3 inside a 
QQC2 app
only difference: customer app is using user 10 (Business app)

thx
ekke

Am 23.11.22 um 10:02 schrieb ekke:
>
> In one of my apps the user must be able to select one or more files 
> from shared data and also to create a new file in a selected directory.
>
> Up to API 29 I did this using QStandardPathes, per ex. for 
> PicturesLocation and DocumentsLocation and have built my own 
> CustomFileDialog.
>
> With API30 QStandardPathes only work with AppDataLocation, but not 
> with external shared data because of ScopedStorage.
>
> Qt support for ScopedStorage is still work-in-progress 
> (https://bugreports.qt.io/browse/QTBUG-98974 
> <https://bugreports.qt.io/browse/QTBUG-98974>)
>
> Tried to use MANAGE_EXTERNAL_STORAGE, because the app is a 
> DropBox-like app to manage files from shared network drives or 
> SharePoints.
>
> cpp:
>
> #define PACKAGE_NAME "package:org.company.package_name"
>
> jboolean value = 
> QAndroidJniObject::callStaticMethod<jboolean>("android/os/Environment", 
> "isExternalStorageManager");
>
> if( value == false )
>
> {
>
> QAndroidJniObject ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = 
> QAndroidJniObject::getStaticObjectField( "android/provider/Settings", 
> "ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION","Ljava/lang/String;" );
>
> QAndroidJniObject intent("android/content/Intent", 
> "(Ljava/lang/String;)V", 
> ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION.object());
>
> QAndroidJniObject jniPath = QAndroidJniObject::fromString(PACKAGE_NAME);
>
> QAdroidJniObject jniUri = 
> QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", 
> "(Ljava/lang/String;)Landroid/net/Uri;", jniPath.object<jstring>());
>
> QAndroidJniObject jniResult = intent.callObjectMethod("setData", 
> "(Landroid/net/Uri;)Landroid/content/Intent;", jniUri.object<jobject>() );
>
> QtAndroid::startActivity(intent, 0);
>
> }
>
> Manifest:
>
> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
> <uses-permission 
> android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
> <uses-permission 
> android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
>
> App asks for permission and sets permission – controlled at 
> settings-apps-special apps-apps with all files access.
>
> But nothing changed – QStandardPathes still gives no access to files – 
> only for internal AppDataLocation.
>
> Any idea what could be missed to get the “old” behaviour back using 
> MANAGE_EXTERNAL_STORAGE permission ?
>
> Looked for workarounds and tried KDAB SharedStorage Library:
>
> https://www.kdab.com/android-shared-storage-qt-wrapper/ 
> <https://www.kdab.com/android-shared-storage-qt-wrapper/>
>
> https://github.com/KDAB/android/tree/master/shared_storage 
> <https://github.com/KDAB/android/tree/master/shared_storage>
>
> YEP - it works, but there’s a drawback:
>
> selecting files only selects one file – haven’t found a way to select 
> multiple files using KDABs SharedStorage library and this is essential 
> for users.
>
> Selecting a folder and then creating a file inside the folder works great.
>
> Then I found out, that QDir and QFile not only support file pathes, 
> but also Content URIs 
> (https://developer.android.com/reference/android/content/ContentUris).
>
> This is not documented yet, because full ScopedStorage support not 
> ready yet (https://bugreports.qt.io/browse/QTBUG-99664 
> <https://bugreports.qt.io/browse/QTBUG-99664>)
>
> But the current implementation helps if using the QML FileDialog on 
> Android 
>
> Select multi files: Using the QML FileDialog I can see the files from 
> different external locations and I can select multi files, what was 
> missing from KDABs SharedStorage. I’m getting a list of ContentUris 
> and can then use QFile directly using the ContentUris 
>
> Create File in folder: I can select a folder, was asked for 
> permission, but then trying to create a file inside the selected 
> folder, I’m getting errors:
>
> E Qt JAVA : openFdForContentUrl(): No permissions to open Uri
>
> and “Unknown error” from QFile, per ex. using 
> "content://com.android.externalstorage.documents/tree/primary%3ADocuments/ekke.txt"
>
> Unfortunately using the QML FileDialog I’m getting some warnings:
>
> W libenbwDOCS_x_arm64-v8a.so: 
> qrc:/android_rcc_bundle/qml/QtQuick/Controls/Styles/Android/LabelStyle.qml:94: 
> TypeError: Cannot read property 'ENABLED_SELECTED_STATE_SET' of undefined
>
> W libenbwDOCS_x_arm64-v8a.so: 
> qrc:/android_rcc_bundle/qml/QtQuick/Controls/Styles/Android/LabelStyle.qml:89: 
> TypeError: Cannot read property 'ENABLED_STATE_SET' of undefined
>
> Conclusion:
>
> Selecting a folder and creating a file I can do using KDABs SharedStorage,
>
> Selecting multiple files I can do using QML FileDialog and have to 
> live with the warnings.
>
> Any better ideas?
>
> Thx
>
> ekke
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> https://lists.qt-project.org/listinfo/interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20221124/07a7e06b/attachment.htm>


More information about the Interest mailing list