DEV Community

RockAndNull
RockAndNull

Posted on • Originally published at rockandnull.com on

Downloading Files in Android with DownloadManager

Downloading Files in Android with DownloadManager

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, 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" />
[...]
Enter fullscreen mode Exit fullscreen mode

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()
}
Enter fullscreen mode Exit fullscreen mode
  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, 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 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!

Top comments (0)