Open theatischbein opened 1 month ago
Thank you very much for opening up this issue! I am currently a bit overwhelmed by the many requests that arrive each week, so please forgive me, if I fail to respond personally. I am still very likely to at least skim read your request and I'll probably try to fix all (real) bugs if possible and I will likely review every single PR being made (please, give me a heads up if you intent to do so) and I will try to work on popular requests (please upvote via thumbs up on the original issue) whenever possible, but trying to respond to every single issue over the last years has been kind of draining and I need to adjust my approach for this project to remain fun for me and to make any progress with actually coding new stuff. Thanks for your understanding!
Hello there theatischbein! 👋
Thank you and congratulations 🎉 for opening your very first issue in this project! 💖
In case you want to claim this issue, please comment down below! We will try to get back to you as soon as we can. 👀
For more open ended discussions and/or specific questions, please visit the discussions page. 💖
I tried to get something out of the logs when choosing the folder if sync is already enabled!
/storage/emulated/0/SupProd
first, when opening the picker, but it does not exist per default.10-14 11:07:35.351 20476 20476 W WindowOnBackDispatcher: OnBackInvokedCallback is not enabled for the application.
10-14 11:07:35.351 20476 20476 W WindowOnBackDispatcher: Set 'android:enableOnBackInvokedCallback="true"' in the application manifest.
10-14 11:07:35.383 20031 20031 D SuperProductivity: Success Folder Pick! Now saving...
10-14 11:07:35.384 20031 20031 D SuperProductivity: onActivityResult
10-14 11:07:35.419 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:07:35.359 1612 1764 W libprocessgroup: SetCgroup::ExecuteForProcess: failed to open /dev/blkio//cgroup.procs: No such file or directory
If sync is disabled and I select an nextcloud folder I get this logs
allowedFolderPath
is only trigger via this way and not when syncing is already enabledfilesyncFolder: /storage
which is not empty. Maybe thats why the behaviour is weird, when sync is disabled and I select the folder ?10-14 11:46:39.765 20476 20476 D PickerActionHandler: onFinished() [content://org.nextcloud.documents/tree/ce7bb7e07d7408712125e64ccbf9c308%2F55]
10-14 11:46:39.771 20476 20476 W WindowOnBackDispatcher: OnBackInvokedCallback is not enabled for the application.
10-14 11:46:39.771 20476 20476 W WindowOnBackDispatcher: Set 'android:enableOnBackInvokedCallback="true"' in the application manifest.
10-14 11:46:39.780 1612 1764 W libprocessgroup: SetCgroup::ExecuteForProcess: failed to open /dev/blkio//cgroup.procs: No such file or directory
10-14 11:46:39.780 1612 1764 W libprocessgroup: SetCgroup::ExecuteForProcess: failed to open /dev/blkio//cgroup.procs: No such file or directory
10-14 11:46:39.793 4993 7890 D DocumentsStorageProvider: queryDocument(), id=ce7bb7e07d7408712125e64ccbf9c308/55
10-14 11:46:39.799 4993 7890 D DocumentsStorageProvider: queryDocument(), id=ce7bb7e07d7408712125e64ccbf9c308/55
10-14 11:46:39.804 4993 7890 D DocumentsStorageProvider: queryDocument(), id=ce7bb7e07d7408712125e64ccbf9c308/55
10-14 11:46:39.810 20031 20031 D SuperProductivity: Success Folder Pick! Now saving...
10-14 11:46:39.810 20031 20031 D SuperProductivity: onActivityResult
10-14 11:46:39.837 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:46:39.843 20031 20031 I chromium: [INFO:CONSOLE(368)] "Checking file access permission for android false", source: https://app.super-productivity.com/main-DUZ4F2RX.js (368)
10-14 11:46:39.849 1612 2658 W UserManagerService: Requested status bar icon for non-badged user 0
10-14 11:46:39.850 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:46:39.853 20031 20031 I chromium: [INFO:CONSOLE(368)] "Granted file access permission for android", source: https://app.super-productivity.com/main-DUZ4F2RX.js (368)
10-14 11:46:39.853 20031 20111 D SuperProductivity: allowedFolderPath grantedPaths: {}
10-14 11:46:39.853 20031 20111 D SuperProductivity: allowedFolderPath filesyncFolder: /storage
10-14 11:46:39.853 20031 20111 D SuperProductivity: allowedFolderPath folderPath.isNotEmpty(): true pathGranted: false
10-14 11:46:39.855 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:46:39.856 20031 20031 I chromium: [INFO:CONSOLE(368)] "Checking file access permission for android false", source: https://app.super-productivity.com/main-DUZ4F2RX.js (368)
10-14 11:46:39.856 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:46:39.856 1612 11266 D ConnectivityService: requestNetwork for uid/pid:10114/2449 asUid: 10289 activeRequest: null callbackRequest: 42659 [NetworkRequest [ REQUEST id=42660, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10289 RequestorUid: 10114 RequestorPkg: com.android.systemui UnderlyingNetworks: Null] ]] callback flags: 0 order: 2147483647
10-14 11:46:39.867 20031 20111 D SuperProductivity: isGrantedFilePermission grantedPaths: {}
10-14 11:46:39.869 20031 20111 D SuperProductivity: allowedFolderPath grantedPaths: {}
10-14 11:46:39.870 20031 20111 D SuperProductivity: allowedFolderPath filesyncFolder: /storage
10-14 11:46:39.870 20031 20111 D SuperProductivity: allowedFolderPath folderPath.isNotEmpty(): true pathGranted: false
I get a prototype to work!
The problem ist that for sp.getString("filesyncFolder", "")
an absolute file path is used and stored. This works for local files but not other mounted file systems.
My approach is to keep it at at the DocumentFile
level:
val fpath = root.uri.toString()
// Open preferences to save folder to path
val sp = activity.getPreferences(Context.MODE_PRIVATE)
sp.edit().putString("filesyncFolder", fpath).apply()
When reading and writing a File I parse the URI from the preferences.
val sp = activity.getPreferences(Context.MODE_PRIVATE)
val folderPath = sp.getString("filesyncFolder", "") ?: ""
val folder = DocumentFile.fromTreeUri(activity, Uri.parse(folderPath))
var file = folder?.findFile(filePath)
It is not fully worked out, but if you @johannesjo I can try to prepare an pull request.
Let me if you are interessted :)
Hey there! Thank you very much for digging into this! So far I was not able to reproduce the behavior. Since you mentioned the problem being caused by mounted file systems I tried using the sd card as target, but all seems to work fine.
May I ask, what you mean by nextcloud folder? Is that something the nextcloud android app creates?
Nevertheless making mounted file systems work better sounds like something we should do :)
@jiongxuan do you agree? Would be great to have your input on this!
Hey, @johannesjo and @theatischbein,
Thanks for looping me in!
First off, I should mention that I haven’t personally used Nextcloud, so my response here is more focused on general Android behavior.
That being said, there are a few things to consider. I’d like to ask which Android version you’re using, @johannesjo.
Starting from Android 10+, Google introduced Scoped Storage, which changed how apps access external storage and manage file permissions. Different Android versions may behave differently, especially when dealing with mounted file systems like Nextcloud.
In my experience, Android file paths generally work well for sandboxed directories, but for external applications (like Nextcloud), it’s best to use DocumentsProvider URIs instead of absolute file paths (even when accessed through DocumentFile). This approach helps avoid permission issues and is more robust across different Android versions.
As for the pull request, I’ve had a look and everything seems well-written. I’d recommend testing it thoroughly to make sure it works in all scenarios, and if everything checks out, we could aim to include this in the next version after the current Capacitor updates.
Feel free to reach out if you have any questions!
BTW: @johannesjo @theatischbein
I’ve reviewed the PR, and overall it’s well-done! However, there’s one important point regarding file access permissions that needs attention, especially considering the changes introduced in Android 11 (API level 30) and beyond.
Starting from Android 11, WRITE_EXTERNAL_STORAGE has been deprecated, and apps can no longer request it. Even if the app already has READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions, they are not enough to handle files accessed via DocumentsProvider, like the Nextcloud folder.
To properly handle access to external files, especially mounted file systems like Nextcloud, we need to request URI-based permissions using:
val takeFlags: Int = (Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
contentResolver.takePersistableUriPermission(uri, takeFlags)
This ensures the app can retain access to the selected folder or file even after being restarted. Without this, the app will lose access to the files once it’s closed or the device is restarted, leading to potential permission issues in future file operations.
For Android versions prior to 11, you can still declare WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE as before.
Overall, the PR looks great! I’d recommend adding this persistable permission handling and thoroughly testing it on newer Android versions.
I’d like to ask which Android version you’re using, @johannesjo.
I've got a pixel 5 with android version 14.
Thank you very much for your input! @jiongxuan
@theatischbein could you make the adjustment that @jiongxuan suggested?
@johannesjo @jiongxuan yes I will create an PR this weekend with the changes!
Thanks for your feedback :)
Moved from https://github.com/johannesjo/super-productivity-android/issues/58
Your Environment
Expected Behavior
Current Behavior
I want use the sync feature with my Nextcloud android client file system integration.
If I start with Sync disabled, I can select my folder and allow file access. Afterwards the file path is not shown, but the error "Needs file access permission".
If I enable Sync first, I can select my folder and allow file access. Afterwars I got the popup error in superproductivity: "Sync Local file permission denied. Your file permission for local syncing has been revoked." I can choose to disable to sync or to "Give permission". If I click "Give permission" I am back at the folder select and can do this in an endless loop.
Using a local folder does work, but I haven't found a way to automatically download files in a folder in Nextcloud client, only for AutoUpload. My idea for a work around was to use
Android/media/com.nextcloud.client/nextcloud/[account]/path/
which does work, but not for fetching remote updates automatically.Steps to Reproduce (for bugs)
First scenario
Second scenario
Can you reproduce this reliably?
yes. I reinstalled the app multiple time from f-droid and GPlay Store and redproduce them in the clean installed environment
Console Output
Error Log (Desktop only)