Downloading to external storage on Android #163
Replies: 4 comments 1 reply
-
May I have some examples of solution number 4 and 5 ? |
Beta Was this translation helpful? Give feedback.
-
Option 3 (a boolean There is a variant (let's call it option 3a) which uses a configuration to set Android to use external storage for all downloads, or for downloads greater than a certain size. For example (you'd only use one):
Option 3a has the advantage of not requiring any change to The more I think about it, the more I think option 3a is the simplest and most consistent of all options. |
Beta Was this translation helpful? Give feedback.
-
@nahidmk this is now available on the |
Beta Was this translation helpful? Give feedback.
-
Implemented in V7.11.0 |
Beta Was this translation helpful? Give feedback.
-
The issue
Android developers would like the option to download directly to a external storage (an SD card), presumably for two reasons:
moveToSharedStorage
introduces an extra copy step which is inefficientDesktop developers would like an option to download to any file path, not only those provided through
BaseDirectory
andSharedStorage
.Considerations
There are 3 concerns to address:
baseDirectory
,directory
andfilename
to determine the location of a file. Creating an option to use an absolute path therefore is confusing and will likely lead to hard-to-fix bugs, especially on iOS. The path to external memory on Android is also not stable (e.g. an SD card can be removed) but from the feedback it seems that this is considered less of an issue, so one we will ignore here. It does mean that downloads to external memory will be less confident and may fail when started.SharedStorage
enums. However, these can only be used in methodmoveToSharedStorage
, as a second step after downloading a file - they cannot be used as download destinations for the initial download. In addition, the introduction of the MediaStore means you can no longer use an absolute path in Android either (which is what the Desktop developers would prefer)For posterity: the reason we use
baseDirectory
,directory
andfilename
to determine the location of a file (instead of a much simpler full path) is that paths on mobile are not stable. iOS, every time you start the app it will get a new sandbox, with a different base path. Because the downloader needs to work for all platforms similarly, this requires us to split the file location in three.Possible solutions
There doesn't appear to be a way to pass a full absolute path to
Task
in a way that works for all platforms, plus it has significant drawbacks. The Desktop developer that needs this can always choose to rename or move a downloaded file to wherever they want using plain Dart code, so I am going to suggest we ignore this request and pursue the route using theSharedStorage
enum as a way to indicate where files should go, and solve for the Android external storage use case only.To solve for the external storage directory in Android, we could:
BaseDirectory.root
to theBaseDirectory
enum, such that the path provided bydirectory
andfilename
effectively becomes a path from root to anywhere. This would satisfy the Desktop developers, but would a) create issues for iOS developers and b) is not implementable in Android because of the MediaStore.BaseDirectory
enum that would equate to external storage on Android. However, this would be very confusing for non-Android developers as those have no true equivalent on those platforms, and appear as duplicates of theSharedStorage
enum.external
toTask
just for Android that if true applies thedirectory
parameter to the external directory. This helps somewhat, but the choice of directories within external storage is not unlimited, and we still have the issue with the MediaStore, which expects files to fall in certain categoriesSharedStorage
fieldexternal
toTask
just for Android that, if not null, forces the download to the appropriate external storage directory. We then need to update theTask.filePath
method to return the proper file path as returned by the MediaStore.BaseDirectory
enums into one of theSharedStorage
destinations. This would allow the same functionality as 4, but set 'permanently' for all future downloads, and without the need for an extra field inTask
.I'm leaning towards solution 4 as the preferred approach, with options for the field: external, androidExternal, sharedStorage, androidSharedStorage and perhaps others.
I also like 5, as it's simple and explicitly requires Android developers to make the choice to change how the downloader works.
To solve for the need to not download to a temporary file in internal storage, we could create a random temporary file in external storage (using the MediaStore) and update the MediaStore with the desired file name once the download completes successfully. We would only do this if the download destination is an external destination on Android - it would not change normal functionality.
Alternatively, we could drop the contract for this type of direct-to-external download, meaning we don't create a temporary file and instead download straight to the desired external destination.
Alternatively we could add a configuration option to activate this direct-to-external download.
Beta Was this translation helpful? Give feedback.
All reactions