Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use DownloadManager to download files to real SD card, not to emulated storage

I have a galaxy S4 and my problem is that i can't use the DownloadManager to download files to SD card, on emulated storage it works just fine, as for real SD card it gives me this error:

java.lang.SecurityException: Destination must be on external storage: file:///mnt/extSdCard/Android/data/net.myApp/files/exercises/exec.mp4

Here is my code:

DownloadManager dwlManager=(DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);

DownloadManager.Request dwlmRequest=new DownloadManager.Request(Uri.parse("http://cdn..."));
File destination = new File("/mnt/extSdCard/Android/data/net.myApp/files/exercises/exec.mp4");              

dwlmRequest.setDestinationUri(Uri.fromFile(destination));
dwlManager.enqueue(dwlmRequest); //<--- Here comes the error.

If i set the destination as:

File destination = new File(getExternalFilesDir(null), "exec.mp4");

The code works just fine, because the destination comes to the emulated storage. Also i can create files to the SD card like:

File f = new File("/mnt/extSdCard/Android/data/net.myApp/files/exercises/exec.mp4");
f.createNewFile();

It works, but i can't use the download manager with that path.

Please help. I need to be able to download files to that path.

like image 945
nolanic Avatar asked Jan 14 '14 15:01

nolanic


3 Answers

This is not supported. There is no guarantee that DownloadManager has any rights to write to arbitrary paths, even if you think they refer to an SD card. Moreover, your own code that uses /mnt/extSdCard/ may work on your device but will not work on all devices, many of which will not even have such a directory.

like image 73
CommonsWare Avatar answered Nov 10 '22 20:11

CommonsWare


According to this: java.lang.SecurityException: Destination must be on external storage

It's not possible for the DownloadManager to write into files in an arbitrary location. But you can download the file to the external storage using the "Enviroment" constants, and after the download has finished, copy the file to the desired location, and finally delete the original file using the standard file API.

like image 22
Fco P. Avatar answered Nov 10 '22 19:11

Fco P.


After spending some time on this problem i found a more optimal solution then copying files to an arbitrary location after download. The main problem is that i was setting the path to SD card incorrect.

It was: /mnt/extSdCard/Android/data...

But on Samsung galaxy S4 it should be: /storage/extSdCard/Android/data...

The default download manager seems to work fine with this path as destination for downloads. On the following link i found a pretty good code for detecting paths to SD card for different devices: http://www.javacodegeeks.com/2012/10/android-finding-sd-card-path.html

It looks haky, but for me, it seems to be the most optimal solution.

like image 2
nolanic Avatar answered Nov 10 '22 20:11

nolanic