Android & Kotlin

Android Download Manager: Comprehensive Guide

Pinterest LinkedIn Tumblr

Learn all about Android download managers and find the best examples out there! How you can use DownloadManager in android to download any type of file from the Internet? This guide will help you understand what they are, and why they are important and provide tips on how to use them with ease.

An Android download manager helps you manage your downloads on the go, whether it is for videos, music, documents, or other types of files. As you become familiar with this system service, you’ll be able to use these features in your app. In this guide, we’ll explain what android download managers are and provide examples of some of the best ones available.

What is an Android Download Manager?

Download manager is a system service, So that comes from android operating system directly and is also managed by android operating system which makes things very easy. It comes with a lot of inbuilt features such as notification with progress. It also popup a notification when the download is finished. It already handles all download serving directly. So it is very easy solution for us to download any file from Internet.

Create a sample app in android studio

Let’s move to Android Studio and create a new application with EmptyActivity template. In this example, I named the app as DownloadManagerExample. Wait till the sync finished.

Create a Downloader interface

For making this android download manager more accessible, I am creating a Downloader Interface. Just navigate the root directory of project and create new interface named Downloader. and write down the below functions.

package com.androidwave.downloadmanagerexample

//return Download id which type is Long.
interface Downloader {
    fun downloadFile(url: String): Long
}

 It will return Download id which type is Long.

Implement Downloader Interface

 Let’s move to the next step just create a new Class that actually implements this downloader Interface like this.

package com.androidwave.downloadmanagerexample

import android.app.DownloadManager
import android.content.Context
import android.os.Environment
import androidx.core.net.toUri

class AndroidDownloader(
    private val context: Context
): Downloader {

    private val downloadManager = context.getSystemService(DownloadManager::class.java)

    override fun downloadFile(url: String): Long {

        return -1
    }
}

Understand how to configure a request

How to configure the download manager request so you’ll be able to take full advantage of their features and make the most out of your android app. see the below point

1. Set the MIME type of our download file

Guys if you have specific use case then you can hardcode the MimeType like for JPEG image it will we image/jpeg for video like video/mp4. Here is a list of common MIME types and helper methods.

// Enter the MimeType type that type file you wish to download  
setMimeType("*/*")

Let automated MIME type based on URL so let write MIME type parse

The above solution will works fine for while you want to download only one type of file, but what about any type of file. No worry I have a complete solution for that. Let’s write a helper function that parsed any kinds of file. So below function will parse any kinds of file.

    private fun parseMimeType(url: String): String {
        val file = File(url)
        val map = MimeTypeMap.getSingleton()
        val ext = MimeTypeMap.getFileExtensionFromUrl(file.name)
        var type = map.getMimeTypeFromExtension(ext)
        type = type ?: "*/*"
        return type;
    }

Set network types

Which type of network you wish to download this file, such as only WIFI or Mobile Network . Based on need what we can do, can setAllowedNetworkTypes(), Like NETWORK_WIFI or NETWORK_MOBILE Network

Set Notification Visibility

 We can also manage notification visibility based on need using this setNotificationVisibility.

  • VISIBILITY_VISIBLE_NOTIFY_COMPLETED – the whole duration of the download and also come notification when the download is finished.
  • VISIBILITY_VISIBLE – That means It will show progress of download but not when it finished
  • VISIBILITY_HIDDEN – Not notification at all
  • VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION –  This one will notify only completion means user only gets a notification when the download succeeds, but not for the progress

Set Title

While file getting downloading notification you can set title that will display on notification. just like below

setTitle("Title")

Add request header

addRequestHeader() builder function only relevant for the authorised header while you downloading any file that have header protection.

Set destination directory

The last but important you want to set destination directory where you wish to download file. In this example I am setting download directory

setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)

Finally enqueue the request

downloadManager.enqueue(request)

Finally, AndroidDownloader class looks like this

package com.androidwave.downloadmanagerexample

import android.app.DownloadManager
import android.content.Context
import android.os.Build
import android.os.Environment
import android.webkit.MimeTypeMap
import androidx.core.net.toUri
import java.io.File
class AndroidDownloader(context: Context) : Downloader {

    private val downloadManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        context.getSystemService(DownloadManager::class.java)
    } else {
        context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    }

    override fun downloadFile(url: String): Long {
        val fileName= getFileNameFromUri(url);
        val request = DownloadManager.Request(url.toUri())
            .setMimeType(parseMimeType(url))
            .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE)
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            .setTitle(fileName)
            .addRequestHeader("Authorization", "Bearer <token>")
            .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
        return downloadManager.enqueue(request)
    }

    private fun parseMimeType(url: String): String {
        val file = File(url)
        val map = MimeTypeMap.getSingleton()
        val ext = MimeTypeMap.getFileExtensionFromUrl(file.name)
        var type = map.getMimeTypeFromExtension(ext)
        type = type ?: "*/*"
        return type;
    }

    private fun getFileNameFromUri(url: String): String {
        return url.substring( url.lastIndexOf('/')+1, url.length);
    }
}

Specify BroadcastReceiver

Specify boradcase revicer So android sytem will send broadcast event to our app to download finished, It will receve callback when download finish. Just create a new class which extends broadcast receiver apply download filter

 

package com.androidwave.downloadmanagerexample

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class DownloadCompletedReceiver: BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        if(intent?.action == "android.intent.action.DOWNLOAD_COMPLETE") {
            val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L)
            if(id != -1L) {
                println("Download with ID $id finished!")
            }
        }
    }
}

Register Broadcast Receiver in android manifest

        <receiver android:name=".DownloadCompletedReceiver" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
        </receiver>

Add internet and WRITE_EXTERNAL_STORAGE permission in android manifest

Open the android manifest file and add below permission. After that you have to manage runtime permission. In this demo I am not implementing runtime permission for that please follow my another artilces Best Practices of Runtime Permissions Android.

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Finally let use the DownloadManager

All setup is done let’s use this download manager where you wish to used. In this example I am using it MainActivity. like below

package com.androidwave.downloadmanagerexample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val downloader = AndroidDownloader(this)
        val fileUrl= "https://androidwave.com/wp-content/uploads/2020/01/navigation-component-in-android.png"

        findViewById<TextView>(R.id.textView).text = fileUrl
        findViewById<Button>(R.id.button).setOnClickListener {
            /** Update the URL of file that you wish to download*/
            downloader.downloadFile(fileUrl)
        }
    }
}

Conclusion

All done about the android download manager example app.  Here I quickly launch my app, Then you can see how it work, If your file bit large then you can see progress bar also. In my example file is very sort so you did not see progress bar because it download very fast. But ended wit download complete with any type of file.

Only once condition is you should have valid download link. Now navigate you download rectory here is download file which can access afterward.

Download full source

Write A Comment