Android DownloadManager


Android DownloadManager Tutorial and Examples
.

The DownloadManager is a system service which we can use to handle long running downloads. In this piece we want to look at the DownloadManager class and several examples.

We will look at issues like the types of downloads you can make with DownloadManager class, how to actually make the requests, how to show progress in status bar via noification, open downloaded file and even remove.

Common Questions

Here are some of the questions to allow us understand the DownloadManager class.

Which Types of Downloads are Handled by DownloadManager

Normally there are several protocols for communications across devices. And certainly download a file is just a form or communicating between atleast two devices. One device supplying a file while another receiving it. Beware the DownloadManager is used to handle only HTTP downloads.

DownloadManager is especially useful if your downlaods are long running.

Where Do the Downloads take Place?

Where with regards to threads. Well the downloads will definitely take place in the background thread.

Why Use the DownloadManager?

Well what are it's advantages? Well we have several. For example

  1. As we said the downloads take place in the background thread. In fact in a background in a system app. This means our app doesn't have to handle the downloads manually in our main thread hence our UI is always responsive.
  2. Secondly the HTTP interactions are abstracted away from us. We don't have to worry about variou HTTP codes and messages and possible failures. In fact even retries are made on our behalf. Yet these retries can amazingly be persisted through connectivity state changes and system reboots.

DownloadManager Examples

Let's look at some DownloadManager examples.

1. Download File, View All Download, Delete Download

In this complete example we want to see how to download a file from the internet using the downloadManager class. Then we can open the donwload by clicking the notification in the system bar or from internally in our app. Moreover we can delete the file, view all downloads etc.

Video Tutorial

Here we have a video tutorial for this example.

Demo

Here's the demo of the app.

Android DownloadManager Example

OverView of the App

  1. User clicks the download button.
  2. Download starts.
  3. Meanwhile the progress is shown in the status bar as a notification. The notification also includes the title and description of the download.
  4. The user is notified via the system status bar text when the download is complete.
  5. When user clicks the notification the file is opened. If it is not found then a toast message is shown.
  6. When user clicks View All button then the view for displaying all the downloads is shown. You may have some other downloads enqueued there, some not from your application.
  7. When user clicks the Delete button then our download whether partial or complete gets deleted.
(a). MainActivity.java

MainActivity as you can imagine is our launcher activity. it will derive from the AppCompatActivity. This is where we write all our code. But first we start by making several imports. These include:

  1. DownloadManager - The class responsible for allowing us use the system download manahger.
  2. Intent - Class responsible for allowing us open the system download manager view.
  3. Uri - Allows us to parse a string url into a Uri from which our file can be downloaded.
  4. Environment - Allow us specify the public directory where our downloaded file will be stored.
  5. Toast - Allow us to show quick messages.

HowTo's

Let's look at several howTos.

(a). How to Initialize the DownloadManager

As a System service, the DownloadManager is not instantiated directly. Instead we will initialize it using the getSystemService() method and cast the resultant object into the DownloadManager class.

    private void initializeDownloadManager() {
        downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    }

(b). How to Create a Download Request

Inside the DownloadManager class is an inner class called the Request class. We can use this class to define our HTTP Request. We conveniently do this via the builder patter.

        DownloadManager.Request request=new DownloadManager.Request(Uri.parse("https://raw.githubusercontent.com/Oclemy/SampleJSON/master/spacecrafts/voyager.jpg"));
        request.setTitle("Voyager")
                .setDescription("File is downloading...")
                .setDestinationInExternalFilesDir(this,
                        Environment.DIRECTORY_DOWNLOADS,fileName)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

Clearly you can see we've pased the Uri into our Request constructor. Then set the title, descrription, destination and notification visibility.

(c). How to enqueue a Download

Enqueueing a download means adding it to the download queue of the download manager. Then the queue will be processed automatically the system. You enqueue a download using the enqueue() method.

        downLoadId=downloadManager.enqueue(request);

This will return us a download id.

(d). How to remove/delete downloaded file

Well you can remove a downloaded file from the download manager using the remove() method of the DownloadManager class. You pass the download id.

    private void deleteDownloadedFile(){
        downloadManager.remove(downLoadId);
    }

Here's the full source code.

package info.camposha.mrdownloadmanager;

import android.app.DownloadManager;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

    private DownloadManager downloadManager;
    private String fileName=null;
    private long downLoadId;

    /**
     * Initialize download manager
     */
    private void initializeDownloadManager() {
        downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        fileName="Voyager";
    }

    /**
     * Set the title and desc of this download, to be displayed in notifications.
     */
    private void downloadFile(){
        DownloadManager.Request request=new DownloadManager.Request(Uri.parse("https://raw.githubusercontent.com/Oclemy/SampleJSON/master/spacecrafts/voyager.jpg"));
        request.setTitle("Voyager")
                .setDescription("File is downloading...")
                .setDestinationInExternalFilesDir(this,
                        Environment.DIRECTORY_DOWNLOADS,fileName)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        //Enqueue the download.The download will start automatically once the download manager is ready
        // to execute it and connectivity is available.
        downLoadId=downloadManager.enqueue(request);
    }

    /**
     * Cancel downloads and remove them from the download manager.
     * If there is a downloaded file, partial or complete, it is deleted.
     */
    private void deleteDownloadedFile(){
        downloadManager.remove(downLoadId);
    }
    private void openOurDownload(){
       //we can open download here
    }

    /**
     * View all downloads in the downloadmanager
     */
    private void viewAllDownloads(){
        Intent intent=new Intent();
        intent.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
        startActivity(intent);
    }

    /**
     * Handle button clicks
     * @param view
     */
    public void clickView(View view){
        switch (view.getId()){
            case R.id.downloadBtn:
                downloadFile();
                break;
            case R.id.openDownloadBtn:
                openOurDownload();
                break;
            case R.id.viewDownloadsBtn:
                viewAllDownloads();
                break;
            case R.id.deleteBtn:
                deleteDownloadedFile();
                break;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initializeDownloadManager();
    }
}
(b). activity_main.xml

We need a layout for our MainActivity. Here's the code.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
android:background="#009688"
tools:context=".MainActivity">

<TextView
    android:id="@+id/headerTxt"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="DownloadManager Example"
    android:textAlignment="center"
    android:fontFamily="casual"
    android:textStyle="bold"
    android:textAppearance="@style/TextAppearance.AppCompat.Large"
    android:textColor="@color/white" />

<ImageView
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:layout_centerHorizontal="true"
    android:src="@drawable/logo"
    android:contentDescription="@string/app_name"/>

<LinearLayout
    android:id="@+id/button_zone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_centerInParent="true">

    <Button
        android:id="@+id/downloadBtn"
        style="?android:attr/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="clickView"
        android:text="Download" />
    <Button
        android:id="@+id/viewDownloadsBtn"
        style="?android:attr/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="clickView"
        android:text="View All" />
</LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_centerInParent="true">
    <Button
        android:id="@+id/openDownloadBtn"
        style="?android:attr/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="clickView"
        android:text="Open" />

        <Button
            android:id="@+id/deleteBtn"
            style="?android:attr/button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="clickView"
            android:text="Delete" />

</LinearLayout>

</LinearLayout>
(c). AndroidManifest.xml

In our AndroidManifest we need to add permissions for internet connectivity as well as for writing to external storage. This is because we download our image from internet and write to our external storage.

Here's my full AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.camposha.mrdownloadmanager">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post