-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does not get absolute paths as claimed. Cannot write to a .txt file #40
Comments
Whether I select from Documents folder or Google Drive, it's returning
|
This is not an issue. It’s a feature actually and that’s the normal behavior. You are trying to load the absolute file path from a cloud file. Cloud files don’t have any actual paths until a copy is cached into the device. If you need to open a cloud file, the picker will load it from you (thus caching) and then you are free to use it and save it if modified. Also you can’t delete files from cloud with file picker. |
The same occurs for Documents folder. |
So why we need WRITE_EXTERNAL_STORAGE permission? |
@Footmau Because cloud files need caching before having a path. If you want to actually access a file within Flutter, you need to have its data saved somewhere and not virtualized. Let’s say you want to modify it, how would you modify a file that is in the cloud? This package is all about let the user access files, not actually pick paths to write despite though that being possible anyway. |
@miguelpruivo Of course, thanks for that features.
|
@Footmau again, that’s hard to handle. That would make sense for an Android only plugin. iOS behaviors completely different. I have trying to keep a seamlessly feature experience between platforms as much as possible, so less experienced users don’t get confused about why one side supports and other don’t, having to create themselves, in app workarounds. This is also happening for getting directory paths in which android supports it quite easily from API 21 and above but iOS doesn’t have that concept. That’s one of the reasons the #23 is still open to discussion. |
I know this is closed, but will add my situation in here too. I'm trying to select a file from the device and store the path so that I can reopen the file again next time the app loads. The file is likely to have changed in the meantime, so loading it from the cache location is no good. I either need the original file path or the user needs to use the picker every time (which isn't a great experience). I'm not sure why I am getting a cached version of the file. Maybe it is because I'm trying to access a file in the Documents folder (in Android) that was created by another app (maybe I can't access it directly anyway)? The files in the Download folder aren't cached. Anyway, if I'm trying to do something that's not possible, sorry for wasting your time. But if local files are sometimes cached for other reason, then it would be great if there was a way to access the path of the original file as well. Thanks. |
If I pick a Dropbox file with this plugin, and write to it, should I see the changes on Dropbox? |
@bradyt no. You don’t have write permissions with it, neither you can have a URI that points to a remote path. Remote files will be loaded and cached for you to use. Afterwards, you can export it and let the user decide where to save to. |
Thank you for clarifying. Do you think I should be able to set up some sort of seamless experience for Android users, by following your project as a tutorial (tutorial in Java ecosystem, Platform Channels, etc), and using concepts from https://developer.android.com/guide/topics/providers/document-provider? I saw the following statement there.
I am under the impression you used SAF in your I am hoping that my app can read and write to files or a directory without the user having to do anything after the initial selection of files or directories. That is, no need to export or upload. Thank you for looking at my situation. |
@bradyt thank you for your suggestion and I've already thought of that, but that means that it would act more like a file manager instead. The purpose of this plugin is to act just as a file picker providing a seamless experience between iOS and Android. With that said, you don't have a similar concept in iOS and that would mean that devs would have to handle the flow in a different way for both platforms. This was already pointed in this answer. As it is currently, you know that it will behave the same way for both iOS and Android, and IMO that's a plus. |
@Stephen-Cronin sorry for being late in response, probably I've might missed it. If your files are being cached, that's probably because they're being loaded from a remote URI (eg. GDrive, Dropbox, etc.) and you can't get an absolute path for those files, that's why they're all cached. However, IMO, you can handle that yourself by creating an app's content directory and when the user loads/picks a file and it is from a cached directory, save it in your app's content folder. |
Sorry I knew I wasn't going to make sense there. What I meant to say was, am I close to accomplishing this if I fork the project? |
@bradyt I'd say yes, but you'll need to work out the Android side implementation side. Also, currently it is supporting all API (from 16 to 28) which makes it also very flexible. Using document provider only, would limit access to API 19 and above. |
Oh, I assumed you were using this. Thank you for the help and pointing out the caveats. I think making progress on storage options for my app will outweigh that drawback. But maybe I'll explore a more complete solution in the future. |
@miguelpruivo Thanks for the response. In my case, I am trying to load a file created by a third party game and stored in the phone's Documents folder (on Android). This is the path to the file on my phone:
It's not a remote URI, it's on the phone, but file_picker is caching it to:
I want to be able to store the direct path, so when the user plays the game and the file changes, they can reload it through my app without needing to go through file_picker again (as it's relatively slower and more clicks etc). The cached version is out of date as soon as they play the game again, so is useless. If I hard code in the direct path, I can open file, so it seems I have permissions to access it even though it's in a Documents folder belonging to another app. Is there anyway file_picker can provide this path? Is there some sort of bug preventing it? Or more likely, something I'm missing? Thanks! |
@Stephen-Cronin this is happening probably because it’s being stored within other apps private content folder (in this particular scenario, the game) so it needs to be cached (copied) to protect direct access. Nevertheless, might to post the full log when you pick the path so I can check the full trace as well as your Thank you. |
@miguelpruivo Thank you! I was on I've attached the log from debug console and the flutter-debug-log.txt It is saying "Caching file from remote/external URI", but above that you can see that the file URI it gets is:
I'm not sure why it has the Pleco URL/namespace in there. I do have the Pleco app installed, but it's not showing up in the Android file picker at all (ie I'm not navigating anywhere near it) and it should have nothing to do with this. Maybe that's the key? As I mentioned before, I can open the file by providing the direct path to it (in the game's folder) and I've now verified that Thanks again for your help. |
@Stephen-Cronin would you mind to run in on a difference device or emulator and see if it's still happening? It looks like you have a third party file explorer installed and its acting as document provider, thus, the URI is handled like an external file (so that explains the caching process). It's not quite easy on Android to cover all the API/ROM when they use third party explorers, that's why I always suggest to stick with the native one (when supported - usually after API 19 in native roms). |
@miguelpruivo I'd have to set up the emulator (install the game, wait for the data to download etc), so I removed FX file explorer (no change) and Plece (change) from my phone. I am on a Samsung Galaxy S7 so it has the Samsung file explorer rather than the default Android one, but not much I can do about that easily (or can expect my users to do). Anyway, now the file URI line is as follows:
So it's gotten rid of the Pleco namespace/URI but is still treating it as external storage. I still have permission to open the file directly from my app if I hardcode the URI in and also to read the file path from the file, but maybe you can't get that through the file picker. I'll try on the emulator tomorrow to see if that's the same. Thanks again for your help. |
@miguelpruivo I tried with an emulator using a stock standard Nexus 5 and got the same thing:
So it looks like it is indeed because the Documents folder is treated as external (unless the one for your app). I guess I'm out of luck. Thanks anyway for your help, it's much appreciated. |
@Stephen-Cronin when you use the It would be great if you could check it directly with that URI, so I can further debug this. Also, can you give me with the steps to replicate this? Thank you. |
I've started a plugin that allows persistent reading writing to a .txt file from local or cloud storage, at https://github.com/bradyt/uri_picker/. Currently it is licensed for public domain, I hope that allows other plugins such as this one to add similar features. |
@bradyt thank you. You should be able to write/read any file with |
I'm confused. So your stance is that when I write to the |
@bradyt if you're picking a file from Documents folder or any other folder, and write directly into to exact same location, it should stay there. However, for some files, such as remote files (GDrive), it will be cached files, and in this particular scenario, you can't write directly in the same folder. I've checked your implementation and you can allow it because you're writing it directly on the native side (Android) by providing the URI. That's a different concept from what Nevertheless, when I get some time, I should further investigate a possibility to cover the good of both ends for a near future. |
I am confused. Your description there seems to conflict with the following. Your library is using Reading from https://developer.android.com/guide/topics/providers/document-provider.
|
Ah, maybe you mean that you can get the content with your library, then use a different means to write back to the original location, like some separate library that does share or export. |
@bradyt sure, the problem with the document provider, is that is only available after API 19, which somehow will remove the 100% coverage that the plugin currently has (starting with API 16). So that's the reason the |
Yes, I agree, the version limitation, as well as getting things to work across platforms, especially to iOS, will take some thought. I hope that my efforts will help one of any of our packages in the ecosystem to take on more functionality. I wanted to get the easiest functionality available for a reasonable subset of potential users, so I jumped at |
I'm very confused by your use of cloud vs local. It really seems to conflict with what I've been trying to clarify. |
Yes, that's another thing that I value and want to keep as long as possible, a seamless experience across each platform, without having some features that works in one but not the other that would make the dev to be aware of such limitations and implement workarounds himself. If it wasn't because of this, some features like picking only a directory (which Android supports but I believe to be at this point impossible on iOS without picking a file) would be already implemented. |
@miguelpruivo Can you tell me precisely which additional functionality your app provides in local files vs cloud files? I'm not seeing the difference in how they're treated. You seem to be suggesting that your library can write to local files, but not to cloud files. But that seems to conflict with what I quoted above. That it's only reading in a cached copy, at best. No way to write back to the original location with the same path your library returns. |
@bradyt your assumption is correct, tl;dr: I let the user pick a file locally, and then extract the absolute path from it so it can be manipulated with Dart directly, whenever it's possible. When you pick a file from a Dropbox, GDrive, etc. you must cache it in order to have a local file to work with. It can be confusing because you may expect to edit directly that file as you have a path, I agree with you. In the end you're just editing a cached copy that you should take care and save somewhere else (if your app should have this feature at all, because you may want only to display, share, etc.). |
Okay, I'll have to try it again soon. Thank you for clarifying. |
Same issue with "Downloads" directory on my Android 8.0 smartphone. I do not reproduce on Android Emulator with an Android 8.0 smartphone Emulated... |
I obtain the good absolute file path if I do not pick the file from the "download" shortcut, but directly in the smartphone's download directory which is /storage/emulated/0/Download/ |
it's not just cloud file. it's simple. please understand properly. your file_picker which supposed to be easily provide real path doesn't do that. it's all about file information not involving file accessing. 3 years and it still doesn't |
I don't understand what this can and can't do.
Can it be used to write to files? I'm getting errors? You say it returns absolute file paths, but that does not look to be true. It seems to copy the filename only, not the path, and put it in private external storage, especially, cache.
So this is not really a file picker. It only copies files temporarily to cache?
The text was updated successfully, but these errors were encountered: