13

I need to download files on my mobile device and make them accessible for other apps (using Android and iOS).

I managed to download a file to the SD card (cordova.file.externalDataDirectory), but this only exists on Android and even then I cannot rely on every device having an SD card.

When I download to the device storage (cordova.file.dataDirectory), the file is private to my app and therefore not accessible for other apps. The file can be opened in the InAppBrowser, but I would prefer to use the respective default app.

Is there a way to get a path to a directory publicly available on all devices?

The paths returned by the solution suggested in https://stackoverflow.com/a/21375812/3432305 are both private on Android...

EDIT:

I think I should describe my use case so it's clearer what I'm trying to achieve: I want to open files from my in app chat using the respective default app (pdf viewer, image viewer etc.). Because the Cordova File Opener plugin only accepts files from the local file system, I need to save them first. But they don't necessarily need to be accessible from outside my app afterwards...

Community
  • 1
  • 1
kolli
  • 1,260
  • 2
  • 13
  • 23

1 Answers1

17

On Android, external storage directories always exist; if the device doesn't have a physical SD card, Android will emulate it. see getExternalStorageDirectory :

Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.

Therefore cordova.file.externalDataDirectory will always resolve. However, for sharing data between apps, you probably want to use cordova.file.externalRootDirectory - External storage (SD card) root. See cordova-plugin-file.

This way you can store files in a place that's easier to access from another app e.g. /sdcard/my_shared_data/

On iOS, it's more difficult to share files because apps are intentionally isolated from each other due to security policy, as Apple's Inter-App Communication Guide says:

Apps communicate only indirectly with other apps on a device

You best bet on iOS is to share the data by synching it via iCloud. See the section Configuring a Common Ubiquity Container for Multiple Apps in iCloud Design Guide, which says:

... perhaps you provide two apps that interoperate and need access to each other’s files. In both of these examples, you obtain the needed access by specifying a common ubiquity container and then requesting access to it from each app.

DaveAlden
  • 30,083
  • 11
  • 93
  • 155
  • Hi, thx for your answer! That solves my problems for Android at least :) I edited my question to further describe my problem. Could you please check if that changes anything for iOS? Regarding the iCloud, the link you provided says not to store "Cache, temporary or large downloaded data files" there, so I would rather not use it... Plus, I'm developing a hybrid app, so I'm a bit limited to the options the Cordova plugins provide.. But I feel this is a very common use case, so there should be an easy solution for iOS too.. – kolli Oct 13 '15 at 08:39
  • 2
    Opening a file in the default application is completely different from sharing files between specific apps, and much easier. [cordova-plugin-file-opener2](https://github.com/pwlin/cordova-plugin-file-opener2) will do exactly as you need for iOS and Android. Just follow the examples as to where to save the files for each platform, and if you have a problem then post an issue on the plugin Github page. – DaveAlden Oct 13 '15 at 08:49
  • I also felt that this should be an easy task.. Nevertheless, I couldn't find a good example for iOS. I now gave it another try using `cordova.file.applicationStorageDirectory` and it seems to work (although the documentation says it's read-only...). Will try it again later using `cordova.file.cacheDirectory` but I guess it should be fine. thx! – kolli Oct 13 '15 at 10:25
  • @kolli Hi, any feedback regarding iOs? I faced the same issue. I'm using externalRootDirectory for Android but no clue for iOs... Thanks! – VinceOPS Oct 27 '15 at 17:21
  • @VinceOPS Hi! I'm using `cordova.file.cacheDirectory` now for iOS and it works like a charm. – kolli Oct 27 '15 at 19:39
  • Great thanks :). I'll try cacheDirectory and FileOpener2 then. Have fun! – VinceOPS Oct 27 '15 at 19:40
  • Is cache safe enough? Wont it be cleaned up from time to time? – michaelbn Oct 10 '16 at 15:14
  • 1
    @michaelbn yes, cache directory can be wiped at any time by the OS – DaveAlden Oct 10 '16 at 15:16
  • @kolli I used `cordova.file.cacheDirectory` in my iOS project with `+ $scope.selectedFile.FileName;` but I am not able to see the downloaded attachment into iOS device. – Pritish May 03 '17 at 10:58
  • @Pritish I only needed to access the file from the same app immediately after downloading it, as mentioned in my edit, and it worked fine via cacheDirectory back then. It's been a while though and I cannot test this on iOS at the moment, sorry... – kolli May 03 '17 at 17:21