Step by Step Guide to Download Files With WorkManager

Rahul Ray
ProAndroidDev
Published in
3 min readMar 4, 2022

--

Hey Android Devs, in this article we will go through a step by step example of implementing a download feature in your apps using WorkManager.
We will be using Jetpack Compose for UI instead of traditional XML layout files.

So, let’s get started with the first step of adding Work Manager to our project.

Step 1: Add workManager dependency to the project

implementation "androidx.work:work-runtime-ktx:2.7.1"

Step 2: Define a File Download Worker

Create a new class called FileDownloadWorker and extend it from CoroutineWorker

Now define two constants objects one for input and output data and other for notifications.

After this, define a function to save files to the Downloads folder from the URL.
Now due to changes in storage APIs in Android 11 onwards, we will for all the SDKs.

Here we have restricted mimeType to Pdf, Png and Mp4 only. You can add others as well. We are using MediaStore for SDK ≥ 29 and ExternalStoragePublicDirectory for the rest. The getSavedFileUri() function will return a URI if the file has been saved successfully, otherwise, it will return null.

Now we need to show notification while saving a file. For displaying notification, we need to add NotificationChannels for Android Oreo onwards.

We only need to show notification while saving of file is in progress. After that we have to cancel it as well.
Now the doWork() method will something look like this.

Step 3: Define File to be downloaded Model

We have added initialized downloadedUri with null as by default we are assuming the file is not downloaded yet and we don’t have its URI
The isDownloading will be used by the composable to know whether the file is downloading or not.

Step 4: Define the composable which will hold File data

ItemFile takes File as a parameter and has two lambda functions to start downloading and open a particular file.
The description depends on isDownloading and downloadedUri of File.
On click of the container we will start downloading if we don’t have downloaded file URI otherwise we will open the file using that URI.

Step 5: Add permissions to your Manifest File (Before you forget)

Step 6: Take permission from user

We will use ActivityResultLauncher to take read and write because oviously onActivityResult is depreciated now.

Since we have permission as well, now we can start defining our work manager and implementing the file download function.
The startDownloadingFile() function will have one File object and three lambda functions to define the current state, i.e; success, failed and running.
This will be a one-time work request since we only need to download one file at a time. We will also add some constraints to this worker request which are necessary such as Internet should be available and storage or battery should not be low.

We will keep track of the current state of worker by the live data provided by workManger.
The complete function will look something like this.

Step 7: Define a dummy File data and implement the rest

To define the data we will make use of mutableStateOf, so that our composable recomposes when the state of file changes.
When the state of workManager changes, we will make changes in the state of file data.
On Success, we will set isDownloading = false and set the downloadedURI to the ouput URI.
On failure, we will set isDownloading = false and downloadedURI = null.
When in running state, we will set isDownloading = true
Once the file is downloaded, on tap of it, the downloaded file will be opened through intent.

When you run the app, you will be asked for permissions, after that once you start downloding it, you can see the progress bar with a notification as well. Once downloaded, you tap to open the downloaded file.

That’s it for this example. See you in the next one.
You can connect with me on LinkedIn and Twitter.

--

--