Notes: 12. Use DownloadManager
The student materials have been reviewed and are updated as of SEPTEMBER 2022.
You’ve upgraded the starter project with a lot of fun features, using the WorkManager. One of the key features of the project is downloading images. and the simplest way to download an image is to use an HTTP connection manually.
But the simplest way may not be the most user friendly way! Luckily for us, Android has a built-in way of downloading files, with a really nice way to show progress to the users. It’s called, the DownloadManager.
The DownloadManager is an API specifically used to download files. It displays a nice notification to users, with the download progress. It also sends a broadcast to the system, once the download finishes.
It’s a very useful way to download files! Let’s see how to implement it!
Open the ImagesFragment. You won’t create any new files here, but rather change the way current code runs. First, remove the downloadImageWorker from the onImageDownload() function, because you’ll use a DownloadManager instead.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.NOT_ROAMING)
.setRequiresBatteryNotLow(true)
.setRequiresStorageNotLow(true)
.build()
val localImageCheckWorker = OneTimeWorkRequestBuilder<LocalImageCheckWorker>()
.setInputData(workDataOf("image_path" to imageUrl))
.setConstraints(constraints)
.build()
val workManager = WorkManager.getInstance(requireActivity())
workManager.enqueue(localImageCheckWorker)
workManager.getWorkInfoByIdLiveData(localImageCheckWorker.id)
Now, within the observer, add the following code:
val isDownloaded = workInfo.outputData.getBoolean("is_downloaded", false)
if (!isDownloaded) {
val file = File(requireContext().externalMediaDirs.first(), imageUrl)
}
If the file isn’t downloaded, you’ll create a new file, and download the image into that file. Then add the code to build a DownloadManagerRequest:
val request = DownloadManager.Request(Uri.parse("$BASE_URL/files/$imageUrl"))
.setTitle("Image download")
.setDescription("Downloading")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
.setDestinationUri(Uri.fromFile(file))
.setAllowedOverMetered(true)
.setAllowedOverRoaming(false)
There’s quite a lot going on here. You build a request, from an Uri. Then you add the title and description of the download notification, and you set the notification to be visible.
After that, you add the File Uri, so the DownloadManager knows where to download the image. And finally, just like with the WorkManager, you’re adding network constraints! :]
Pretty neat, huh? All of this in a small builder. Now, to enqueue the request, add the final piece of code:
val downloadManager = requireContext().getSystemService(DownloadManager::class.java)
downloadManager?.enqueue(request)
Good job! Now run the project, and check if the download still works!
One thing you can do with the emulator is slow its network speed, to simulate a slow download. With that, you can see the download notification! :]