Downloading Files in Android with DownloadManager
Tags: android
Published: 2023-10-14 14:25:19

---
title: Downloading Files in Android with DownloadManager
published: true
date: 2023-10-14 14:20:49 UTC
tags: Android
canonical_url: https://www.rockandnull.com/downloading-files-in-android-with-downloadmanager/
---

 ![Downloading Files in Android with DownloadManager](https://images.unsplash.com/photo-1521106047354-5a5b85e819ee?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wxMTc3M3wwfDF8c2VhcmNofDZ8fGludGVybmV0fGVufDB8fHx8MTY5NzI5MDgyMHww&ixlib=rb-4.0.3&q=80&w=2000)

It's quite a common scenario to allow attachments or files to be downloaded onto the user's device in an Android app. These can be attachments in a chat or any other file that you want your users to save to their devices.

The [`DownloadManager`](https://developer.android.com/reference/android/app/DownloadManager), a class provided by the Android OS since version 2, is the most convenient solution to implement this functionality. Even though the API is quite straightforward, the necessary permissions are not. To use the `DownloadManager` up until Android 10,  you had to request  `WRITE_EXTERNAL_STORAGE` permission. And how you are requesting permissions has changed over time. You used to just declare them in the `AndroidManifest` on-install time, then request them on run time. After Android 10, you don't even need to request that permission if you are downloading in a public download folder, such as the `Downloads` folder. So, what should have been a very straightforward API call, has become a quite complicated if-then-else scenario.

In this post, I will attempt to provide you with a complete working code for using the `DownloadManager` to download a file from the web and save it into the `Downloads` folder.

## The AndroidManifest

As mentioned above, after Android 10 you don't need to ask for any permission to save a file in the Downloads folder. So there's no need to add the `WRITE_EXTERNAL_STORAGE` permission in the AndroidManifest. Thankfully, there's a way to declare permission only for specific versions of Android to not overdeclare permissions when not needed.

```
[...]   
   <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
[...]
```

_AndroidManifest.xml_

## The code

```
private fun downloadFile(url: String) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && // 1.
            ContextCompat.checkSelfPermission( // 2.
                requireActivity(),
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            )
            != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions( // 3.
                requireActivity(),
                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                1
            )
            Toast.makeText( // 4,
                requireContext(),
                "Permission denied. Grant permissions and try again.",
                Toast.LENGTH_LONG
            ).show()
            return
        }

        val request = DownloadManager.Request(Uri.parse(url)) // 5.
           .setNotificationVisibility( // 6.
           DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
           .setDestinationInExternalPublicDir( // 7.
           Environment.DIRECTORY_DOWNLOADS, "filename_to_save")
        downloadManager.enqueue(request) // 8.
        Toast.makeText( // 9.
            context, "Download started", Toast.LENGTH_SHORT
        ).show()
}
```

1. We need to request permissions only if the device is running Android 10 and below. A reminder that this [applies only for saving to public folders](https://developer.android.com/reference/android/app/DownloadManager.Request#setDestinationInExternalPublicDir(java.lang.String,%20java.lang.String)), such as Downloads.
2. Use this `ContextCompat` method to check if the necessary permissions are already granted.
3. This `ActivityCompat` method allows you to request the necessary permissions without worrying about how the permissions are requested for each Android version.
4. Notify the user that the download cannot proceed due to missing permissions and ask them to try again after granting the permissions.
5. The `DownloadManager` request builder for constructing the request. Obviously, the URL is a required parameter.
6. Define how to communicate to the user about the download and its progress. Here we choose to show the progress of the download in the notification area and show a download completed notification when it's done. Check the [documentation](https://developer.android.com/reference/android/app/DownloadManager.Request#setNotificationVisibility(int)) for additional options.
7. Define where the file should be downloaded. The public Downloads folder required no permissions in Android 10+.
8. Add the request to the `DownloadManger`'s queue to be executed when possible.
9. Notify the user that the request has been added to the queue, and the download should start.  

That's it! You can now allow the users of your app to download any file from the internet.

Happy coding!