14

Downloading a file using the Android DownloadManager to the external storage fails on Samsung Galaxy S9, S9+ on Android 9 (Pie).

Download works for Samsung Devices with Android 8 or other devices with Android 9( e.g. Pixel 2)

I have added to the manifest the following permissions:

 "android.permission.WRITE_EXTERNAL_STORAGE", 
 "android.permission.READ_EXTERNAL_STORAGE",
 "android.permission.INTERNET"

I have also requested READ/WRITE_EXTERNAL_STORAGE permissions at runtime.

The file path is: /storage/4295-DDD5/Android/data/com.example.myapplication/files/filename.file and this filepath exists, I have created it using the Device File Explorer of AndroidStudio

The method which creates a download:

public void downloadFile(String url, String filePath) {
   DownloadManager mDownloadManager = 
   (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);

   DownloadManager.Request request = new 
   DownloadManager.Request(Uri.parse(url));

   request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | 
   DownloadManager.Request.NETWORK_WIFI);

   request.setVisibleInDownloadsUi(true);

   request.setDestinationUri(Uri.parse("file://" + filePath));

   mDownloadManager.enqueue(request);
}

The expected result is the download of the specified file from the url to the filePath instead I am getting the following errors in logs:

D/DownloadManager: [8616] Starting com.example.myapplication
W/DownloadManager: [8616] Stop requested with status FILE_ERROR: Failed to generate filename: java.io.IOException: Permission denied
D/DownloadManager: [8616] Finished with status WAITING_TO_RETRY
V/DownloadManager: MIME Type = application/octet-stream
I/DownloadManager: Download 8616 finished with status WAITING_TO_RETRY
I/DownloadManager: Notification Clear Download 1:com.example.myapplication
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Oagar
  • 161
  • 1
  • 5
  • I found the same issue over at the PocketMaps repository: https://github.com/junjunguo/PocketMaps/issues/104 Also I can reproduce this error on a Pocophone F1 with Android Pie. – miracula May 18 '19 at 18:31
  • Hi! Do you have any news\solution on this issue? I'm facing exact same problem with Galaxy Tab A and Pie. DownloadManager just don't writing to sd-card, only to internal, Environment.getExternalStorageDirectory() returns internal path too. But my code also works on other android devices. – Kasem Anerin Jan 15 '20 at 12:16

3 Answers3

1

I managed to get it working by using setDestinationInExternalFilesDir (with null as second parameter).

This should store the file exactly in the same location as requested, however the actual implementation seems to work on Samsung devices. Also I do not request any permission (*_EXTERNAL_STORAGE).

hrach
  • 2,443
  • 2
  • 26
  • 37
  • That's a great news! I knew the problem is not in permissions, but rather in directory location. – Alex Bravo May 22 '19 at 16:59
  • Hi hrach, I am having the exact problem as mentioned in the question! Can you expand on how the null second parameter helped you? Also, since you send that as null, how do you set a name for the downloaded file? – Sagar May 25 '19 at 13:24
  • 1
    Hi @Sagar, the call I use now is `setDestinationInExternalFilesDir(context, null, fileName)` the filename is just filename in the dir selected by the method. The final URI you may retrieve by `cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))` – hrach May 25 '19 at 15:00
  • 1
    @hranch tried out `request.setDestinationInExternalFilesDir(mContext, null, filePath);` it places the file here: `InternalStorage\Android\packageName\files\filepath` on a Samsung Galaxy S8 with Android 9. Is there anything else you have done? The problem is that we cannot get the DownloadManager to place the files on the ExternalStorage. – Oagar Jun 13 '19 at 11:09
0

Oagar, what have helped me in the past is reading all 8 "The Death of External Storage" blog posts from https://commonsware.com/blog/archive.html

I think the root cause is hiding in this:

The file path is: /storage/4295-DDD5/Android/data/com.example.myapplication/files/filename.file and this filepath exists, I have created it using the Device File Explorer of AndroidStudio

Just because you have created this directory and see it doesn't mean your app is able to write into it. So try writing somewhere you know for sure you can write files.

Hopefully this will help you.

Alex Bravo
  • 1,601
  • 2
  • 24
  • 40
  • 3
    The filepath selection is done with the following method `ContextCompat.getExternalFilesDirs(context, null);`. The bug is that DownloadManager, an Android API component does not have access to the “isolated storage sandbox” of the application. If I use an input stream: `InputStream in = new URL(fileUrl).openStream(); Files.copy(in, Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);` everything works and files are downloaded to the location. – Oagar Jun 13 '19 at 11:14
  • https://stackoverflow.com/users/1911218/oagar I am facing the similar problem, using download manager and need to store files on SD Card. Getting the same error on Android Pie. Could you explain a bit more that how did you solve your problem? May be provide the sufficient code? – Shoaib Mushtaq Oct 09 '19 at 14:51
  • This answer does not help in this case. This seems to be actually a bug in Samsung's latest firmware not with any permission or the @Oagar code. I am facing the same issue with my app which is working fine on a multitude of devices and Android 4 to 10... except for Samsung's latest Android 9. – Andy Oct 15 '19 at 16:53
0

Add this line in your android manifest:

<application
    ...
    android:usesCleartextTraffic="true"/>

(more information in the official doc)

momvart
  • 1,737
  • 1
  • 20
  • 32