No Image
Programming

Android Download Manager Tutorial

Last updated at 21-11-2021

How to download a file from URL in Android

Some common Questions Answered in this Guide are.

  • How to use Download Manager in Android using Example?
  • How Download Manager and Download Files from URL to Android App?
  • How to Download files in Android Local Storage the Right Way?
  • How to Download Multiple Files in Android Programmatically using Java
  • Download Manager Basics for Android Development
  • Download Manager Sample Application in Android
  • Download File from URL in App's Internal Storage using Download Manager in Android Programmatically

Introduction to Download Manager in Android

Android has many built-in libraries and services which make it simple for developers to use existing functionalities for various use cases and let developers focus on their Android Application's Core working and features. Downloading a file from a URL and keeping it available on Android's Local Storage is an essential feature that many apps rely on to make useful features in the App. Downloading File from URL in Android is not as simple as making HTTP Request and storing bytes stream in local storage, however, there are challenges that will be needed to tackle like handling the following exception/events:

  • Networks Connectivity Breaks
  • On Error Detections and Retrying
  • Downloading Multiple Files
  • Listen to Download Completion Events
  • Showing Notification with Progress Bar
  • Cancelling Download Requests
  • Download Over WiFi or Metered Connection
  • Concurrent File Downloads (Simultaneously Download Files)

All these events if we were to handle using our own logic and code it will divert us from our App's Core working, making our app to take more time and effort to manage and release. Android Framework Introduced Download Manager System Service Classes which can be called from your application programmatically assign download job to Download Manager, we can get notified in-app about specific download file tasks requested by our app.

Let's see how we can use the Android Download Manager to Download a File from a URL or Multiple Files.

Sample Application using Download Manager

This application uses Download Manager to request Download

Sample Application using Download Manager

Basic Download Manager Working in Android

Download Manager in Android is a system service that handles process requests by each application in an SQLite DB for managing Download Requests. This means if our app requests some download task using Download Manager, our app will be able to query all the download requests and perform various actions as per the status of download requests.

Now in the above explanation Download Requests and Download Query are the common tasks that our app should be able to do to leverage the rich features of Download Manager in Android. Download Manager comes loaded with 2 nested classes namely DownloadManager.Query and DownloadManager.Request as per the official Download Manager Documentation.

DownlaodManager.Request can be used to set information about the new Download Request that our applications want to make.

DownloadManager.Query helps in filtering the status of the app's download requests.

Download Manager is android sends various Broadcast Intents (a way in which Android notifies other apps about certain actions that happen in android) to our app which can be subscribed/detected by our app to take some action.

A common example of Broadcast Intent Action is as follows:

  • Detecting the Network Connectivity Changes in App to take relevant action. Most apps show us No Internet Connected Error when the device loses network connections. The app actually gets the Broadcast Intent Action that the device connections are lost or regained.

In the same way, Download Manager sends an ACTION_DOWNLOAD_COMPLETE Broadcast Intent to our app when requested files are downloaded by Download Manager. There are many more Broadcast Intent Action by Download Manager that can be detected which can be seen in this list by Android official documentation on Download Manager.

With the understanding of DownlaodManager.RequestDownloadManager.Query, and ACTION_DOWNLOAD_COMPLETE we can use the functionality of Download Manager to achieve the file downloading URL feature in our app. The following steps will show all the major steps that we need to take to Download a file from a URL using Download Manger.

Step 0: Requirements for Download Manager

Download Manager is available to use from API 9 onwards, meaning that all Android Phones with Android Version 2.3 - 2.3.2 and above will be able to get Download Request from our app and perform the download task.

Step 1a: Declare Permissions in Manifest.xml File

Download Manager needs a few Permissions to be declared in our app's Manifest.xml. These permissions are not asked from users but declared in the Android app's Manifest file.

 <!--    Internet Access Permission -->  
 <uses-permission android:name="android.permission.INTERNET" />  
   
 <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />  
   
 <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />  
 
 <!-- In case you want to Download The File Without Showing Notification -->l̥
 <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
 

Step 1b (Optional): Allow Traffic Over HTTP (Only if Files are to be Downloaded from HTTP Source)

Allow HTTP Traffic in Application Attributes in Manifest.xml File so files which have HTTP are also permitted to be downloaded. By default android:usesCleartextTraffic is false/disabled in app.

 android:usesCleartextTraffic="true"
 

Step 2: Getting Instance of Download Manager Service

Using getter method named getSystemService with DOWNLOAD_SERVICE filter to get DownloadManager object. Following Line will use the Context of our android application and get DownloadManager Instance.

 DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
 

Step 3: Download.Request to set infomation about new Download Request

Download.Request object is where information regarding Download is added so DownloadManager can perform as per desired behavior.

 DownloadManager.Request newDownloadRequest = new DownloadManager.Request(Uri.parse(downloadUrl))  
         .setTitle(fileDestination.getName()) // Title  
   .setDescription("Download Manager Content") // Description of the Download Notification  
   .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE) // Visibility of the  
   .setDestinationUri(Uri.fromFile(fileDestination)) // Uri of the destination file  
   .setAllowedOverMetered(true) // Set if download is allowed on Mobile network  
   .setAllowedOverRoaming(true); // Set if download is allowed on roaming network  
   
 // enqueue the Download. Request to Download Manager.  
 downloadTaskId = downloadManager.enqueue(newDownloadRequest);
 

  • setTitle value will be shown in Download Manager Progress Notification in the above case we enter the fileName as the title shown with a green mark.
  • setDescription will set the description of download as shown in the image with an orange mark.
  • setNotificationVisibility is an option to choose if the download is to be shown to the user in the Notification Bar.
  • setDestinationUri is the Uri where the Download Manager should store the file. Uri.fromFile(fileDestination) can convert File object to Uri.
  • setAllowedOverMetered() and setAllowedOverRoaming() are available if you want to choose if the file should be downloaded over specific network. Disabling these options is ideal for Large file download requests. 

DownloadManager Enqueue New Download Request

 downloadTaskId = downloadManager.enqueue(newDownloadRequest);
 

downloadTaskId will hold the Download Task Id. This ID is returned by the enqueue function. Download ID can be used by our app to get specific information about Download at anytime using Download. Query Class.

Step 3: Define and Register BroadcastReceiver

 // Fetching the download id received with the broadcast  
 BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {  
     @Override  
   public void onReceive(Context context, Intent intent) {  
         // if you want to take some action for specific download id  
  // you can experiment with this and use this id 
  // following id is NOT USED in this program and logic  
 
 long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);  
  
 // Checking if the received broadcast is for our enqueued download by matching  download id 
 
   AsyncTask.execute(new Runnable() {  
             @Override  
   public void run() {  
   // following function will run when the download complete intent is recieved
                 getDownloadInfoAndExtractDownloadedFile();  
             }  
         });  
     }  
 };
 

Broadcast Reciever Intent Register to Android using register receiver function

 context.registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
 

Above Code will register the on download complete BroadcastReceiver which will trigger a function to extract a downloaded file and take relevant action.

Download.Query to get Status of ALL Download Requests and Take Relevant Action

 DownloadManager.Query query = new DownloadManager.Query();  
 Cursor c = downloadManager.query(query);
 if (c.getCount() != 0) {  
     while (c.moveToNext()) {  
         long downloadId = c.getLong(c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));  
         String downloadTitle = c.getString(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE));  
         String publicUrl = c.getString(c.getColumnIndexOrThrow(DownloadManager.COLUMN_URI));  
         String filePath = c.getString(c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI));  
         int reason = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
         int status = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));  
 		Log.i("Download File Info", "-------------Starts--------------");  
 		Log.i("Download File Info", "Public URL: " + publicUrl);  
 		Log.i("Download File Info", "Title/Filename " + downloadTitle);  
 		Log.i("Download File Info", "Local URI " + filePath);  
 		Log.i("Download File Info", "Status " + status);  
 		Log.i("Download File Info", "Reason " + reason);  
 		Log.i("Download File Info", "DownloadID " + downloadId);  
 		Log.i("Download File Info", "**********************************");
 		if (status == DownloadManager.STATUS_SUCCESSFUL) {
 			Log.i("Download File Info", "Downloaded + " + downloadTitle + " Status " + status);
 			// TAKE ACTION WHEN THE FILE WAS FOUND COMPLETELY DOWNLOAED
 			
 		}else if (status == DownloadManager.STATUS_RUNNING) {  
 		    // wait for status to be 8 (successfull)  
 			Log.i("Download Manager", "Downloading a file " + downloadTitle + " Status: " + status);  
 		} else if (status == DownloadManager.STATUS_PENDING) {  
 		    Log.i("Download Manager", "PENDING = " + status);  
 		}
      }
  }     
 

Remove A Download Request by Download ID

In some cases, the user might want to cancel the download request so the DownloadManager class has a method to remove which takes the download id as argument to cancel or delete the request.

 /**  
  * Removing file from download queue */  
 private void remove(long downloadId) {  
     downloadManager.remove(downloadId);  
 }
 

Unregistering the DownloadManager BroadcastReceiver when the app is killed.

 @Override  
 public void onDestroy() {  
     super.onDestroy();  
     // Unregister the Download On Complete Listener  
   unregisterReceiver(downloadManagerHelper.onDownloadComplete);  
 }
 


Related post

Newsletter Subscribe maillist!

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the Lorem Ipsum has been the