Android DownloadManager Example [Complete Tutorial]

downloadmanager example
Spread knowledge

We have a separate tutorial section on this website for HTTP operations. Over there we have already covered all the different network operations like sending a GET/POST request, uploading images, logging request, adding headers etc. We have used two of the most popular Libraries- Volley and Retrofit which provide complete support for all these network operations. But when it comes to downloading large files you cant use Retrofit or Volley, both of these recommend using DownloadManager. And that is what today’s tutorial is all about – DownloadManager Example

The DownloadManager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file.

Here are some advantages of using DownloadManager

  • It performs all the HTTP interaction on background thread by default. You dont need to create any thread.
  • It gracefully handles connectivity issues if the network changes or device reboots by automatically retrying download after failure due to any reason.
  • It provides features like pause/ resume download thereby improving user experience.
  • Has a in built mechanism  to inform the user of download progress using notification.

Downloading a File

In this section of DownloadManager Example we will prepare our download request and initiate the File Download  

Add Permissions

First step in this DownloadManager Example is to add INTERNET permission to the AndroidManifest.xml

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

Create Activity

We need to create only one Activity in this DownloadManager Example which will have a button to initiate the download of file. Following is the layout file for this activity

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.irshadkumail.downloadexample.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:id="@+id/download"
        android:text="DOWNLOAD"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content" />


</RelativeLayout>

Now in our Java file of the Activity we initialize the button and set up a click listener as shown below

public class MainActivity extends AppCompatActivity {

    private Button button;

    private long downloadID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button=findViewById(R.id.download);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            }
        });
    }
}
  • Note that we have also created a global long variable which will be used to store download identifier id. More about this in next section

Prepare the DownloadManager.Request

Before starting the download we need to create a  DownloadManager.Request object with all the details of the download and conditions to start it. DownloadManager.Request has provided us with multiple APIs to set information necessary to begin the download. The only mandatory information to start a download is network URI. Even if you have not specified any destination, Android stores the downloaded file in a shared storage . Below code snippet shows how we prepare our DownloadManager.Request with all the details.

       File file=new File(getExternalFilesDir(null),"Dummy");
       /*
       Create a DownloadManager.Request with all the information necessary to start the download
        */

       DownloadManager.Request request=new DownloadManager.Request(Uri.parse("http://speedtest.ftp.otenet.gr/files/test10Mb.db"))
               .setTitle("Dummy File")// Title of the Download Notification
               .setDescription("Downloading")// Description of the Download Notification
               .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)// Visibility of the download Notification
               .setDestinationUri(Uri.fromFile(file))// Uri of the destination file
               .setRequiresCharging(false)// Set if charging is required to begin the download
               .setAllowedOverMetered(true)// Set if download is allowed on Mobile network
               .setAllowedOverRoaming(true);// Set if download is allowed on roaming network

     
   

Following are some important APIs used to set information of the download

  • setNotificationVisibility(int)
    This API is to control whether a system notification is shown while this download is running or when it is completed.
    It can takes any of the following predefined values: 
    #VISIBILITY_HIDDEN
    #VISIBILITY_VISIBLE 
    #VISIBILITY_VISIBLE_NOTIFY_COMPLETED
    If set to VISIBILITY_HIDDEN, this requires the permission android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
  •  setDescription(String), setTitle(String)
    These APIs are used to set the description and title of the download notification (if displayed).
  • setDestinationInExternalFilesDir(Context ,String,String) , setDestinationUri(Uri), setDestinationInExternalPublicDir(String,String)
    These APIs are used to set the destination file path of the downloaded file. You can start a download even without specifying the destination, in which case file is temporarily stored in shared storage. Also if you are storing the file in external storage you need to add STORAGE permissions in the Manifest.
  • addRequestHeader(String,String)
    This API is used to add a request header to the HTTP request used to download the file

Apart from these they are a lot of other APIs like setAllowedOverRoaming(), setRequiresCharging(), setAllowedOverMetered()  etc which define the conditions for the download to start. We have not used all the APIs in this DownloadManager Example but you can read more about them here.

Initiate the download

Once the DownloadManager.Request is ready with all the information you can start the download as shown in snippet below

DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
  • enqueue(request) returns  a unique long ID which acts as an identifier for the download. Note that calling enqueue() doesnt necessarily start the download immediately. It rather schedules the download request in a queue. Once the DownloadManager is free is starts the download.
  • Important thing to note is how we initialize global variable downloadID . enqueue() returns an ID for the download, unique across the system. Global variable downloadID is used to store this ID. It is used to reference this download in future.

Listen to Download Complete

So far in this DownloadManager Example we saw to initiate downloading a file in Android. This section covers how to be notified when your download is completed.

One thing to note is that DownloadManager  is a separate system service which downloads files requested by client. Here your app is the client and once you call enqueue() from your app it is now the responsibility of DownloadManager to schedule that download and save the file at destination. Therefore it is important that the client is informed when the download is completed. Android DownloadManager sends a ACTION_DOWNLOAD_COMPLETE broadcast intent when any download is completed. You can listen for this broadcast using a BroadcastReceiver and identify if your download is completed using the unique long ID returned by enqueue().

Not sure what Broadcast is and How does BroadcastReceiver work?  Read this simple tutorial

You can be notified when your download is complete by following three steps

  • Create a BroadcastReceiver as shown in snippet below.Inside the receiver we just check if the received broadcast is for our download by matching the received download id with our enqueued download.
    private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
           @Override
           public void onReceive(Context context, Intent intent) {
    
               //Fetching the download id received with the broadcast
               long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
    
               //Checking if the received broadcast is for our enqueued download by matching download id
               if (downloadID == id) {
                   Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
               }
    
           }
       };
  • Once the BroadcastReceiver is created you can register for ACTION_DOWNLOAD_COMPLETE in the onCreate method of your activity. This ACTION_DOWNLOAD_COMPLETE broadcast is fired everytime any file download is completed by DownloadManager.
    @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
    
           button=findViewById(R.id.download);
           registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
           button.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                   beginDownload();
               }
           });
       }
  • It is also important that you unregister the BroadcastReceiver in onDestroy. This ensures you only listen for this broadcast as long as the activity is active
    @Override
      public void onDestroy() {
          super.onDestroy();
          unregisterReceiver(onDownloadComplete);
      }
    

     

DownloadManager Example: Complete Code

This completes DownloadManager Example. Below is the complete code of your Activity

public class MainActivity extends AppCompatActivity {

    private Button button;

    private long downloadID;

    private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            //Fetching the download id received with the broadcast
            long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

            //Checking if the received broadcast is for our enqueued download by matching download id
            if (downloadID == id) {
                Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button=findViewById(R.id.download);
        registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                beginDownload();
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(onDownloadComplete);
    }

    private void beginDownload(){

        File file=new File(getExternalFilesDir(null),"Dummy");
        /*
        Create a DownloadManager.Request with all the information necessary to start the download
         */

        DownloadManager.Request request=new DownloadManager.Request(Uri.parse("http://speedtest.ftp.otenet.gr/files/test10Mb.db"))
                .setTitle("Dummy File")// Title of the Download Notification
                .setDescription("Downloading")// Description of the Download Notification
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)// Visibility of the download Notification
                .setDestinationUri(Uri.fromFile(file))// Uri of the destination file
                .setRequiresCharging(false)// Set if charging is required to begin the download
                .setAllowedOverMetered(true)// Set if download is allowed on Mobile network
                .setAllowedOverRoaming(true);// Set if download is allowed on roaming network

        DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
    }


}

 

We hope you are now clear on how to download files on Android. You can even learn how to upload files on Android by reading this simple tutorial


Spread knowledge

2 Replies to “Android DownloadManager Example [Complete Tutorial]”

  1. I have followed your tutorial well, but the output from the download file is in the form of .html instead of the original file. I downloaded the file from the Google Drive link.

    what’s the solution?

Leave a Reply

Your email address will not be published. Required fields are marked *