Using DownloadManager

If we wish to download files or resources but do not need fine control over the actual download, we can hand the task over to the DownloadManager instance.

How to do it...

We can use the DownloadManager instance to initiate, cancel, and query downloads:

  1. As with normal HTTP requests, we need to request permission to access the Internet:
    [assembly: UsesPermission(Manifest.Permission.Internet)]
  2. Then, we get hold of DownloadManager so that we can work with it:
    var manager = DownloadManager.FromContext(this); 
  3. Once we have the manager, we can start downloads using the Enqueue() method with a DownloadManager.Request instance:
    var request = new DownloadManager.Request(Uri.Parse(uri));
    long downloadId = manager.Enqueue(request);
  4. We can also specify whether we only want the download to progress on Wi-Fi, mobile data, or both by using the DownloadNetwork flags enumeration:
    request.SetAllowedNetworkTypes(DownloadNetwork.Wifi);
  5. If we want to cancel a download, we pass the download ID to the Remove() method:
    var removed = manager.Remove(downloadId);
  6. To obtain the progress or state of a download, we pass an instance of DownloadManager.Query to the InvokeQuery() method:
    var query = new DownloadManager.Query();
    query.SetFilterById(downloadId);
    ICursor cursor = manager.InvokeQuery(query);
  7. Once we have the cursor, we can query the result just as we would with a content provider:
    if (cursor.MoveToFirst()) {
      var statusIndex = cursor.GetColumnIndex(
        DownloadManager.ColumnStatus);
      var soFarIndex = cursor.GetColumnIndex(
        DownloadManager.ColumnBytesDownloadedSoFar);
      var totalIndex = cursor.GetColumnIndex(
        DownloadManager.ColumnTotalSizeBytes);
    
      int status = (DownloadStatus)cursor.GetInt(statusIndex);
      double soFar = cursor.GetDouble(soFarIndex);
      double total = cursor.GetDouble(toitalIndex);
      string progress = (soFar / total).ToString("0.00 %");
    }

If we want to be notified when the download is completed, is canceled, or fails, we register a BroadcastReceiver instance with the activity or service:

  1. We need to create an instance of BroadcastReceive that will handle the download event:
    private class DownloadReceiver : BroadcastReceiver {
      public override void OnReceive(
        Context context, Intent intent) {
        long downloadId = intent.GetLongExtra(
          DownloadManager.ExtraDownloadId, 0);
      }
    }
  2. Once we have the download ID, we can query the DownloadManager instance as we normally would:
    var manager = DownloadManager.FromContext(context);
    var query = new DownloadManager.Query();
    query.SetFilterById(downloadId);
    ICursor cursor = manager.InvokeQuery(query);
    if (cursor.MoveToFirst()) {
      // handle the download
    }
  3. In order to register the receiver with the activity or service, we use the RegisterReceiver() method:
    var filter = new IntentFilter(
      DownloadManager.ActionDownloadComplete);
    receiver = new DownloadReceiver();
    RegisterReceiver(receiver, filter);
  4. And we must make sure that we unregister it when we no longer need it:
    if (receiver != null) {
      UnregisterReceiver(receiver);
    }

We can also display the Android Downloads app, if our app downloads files that can be accessed by the user directly:

  1. If we want to open the native Downloads app, we use an Intent instance:
    var intent = new Intent();
    intent.SetAction(DownloadManager.ActionViewDownloads);
    StartActivity(intent);

How it works...

If we have an app that downloads large files, we can use the DownloadManager instance. The DownloadManager instance is useful because it will manage our downloads for us, for example by retrying downloads after the network connection is lost or the device is restarted. It will also broadcast an action when the download is completed.

Tip

The DownloadManager instance can be used to manage the download process, including the handling of network issues, and broadcast an action when it has completed.

Once we have the DownloadManager instance, we can start queuing up downloads using the DownloadManager.Request type and the Enqueue() method. The request is constructed with a URI, but can have several additional properties set.

We could set the download to be invisible to the user by passing false to the SetVisibleInDownloadsUi() method, or we can specify on which types of network the download can run via the SetAllowedNetworkTypes() method.

Tip

Downloads can be hidden from the Downloads app as well as prevented from displaying progress notifications.

When a download is queued, the Enqueue() method will return an ID for the download. We can use the ID to find out the progress or state of the download. If we want to query the status of a download, we construct a DownloadManager.Query instance and set the filter via the SetFilterById() or SetFilterByStatus() methods.

Once we have a query, we can get results by invoking the InvokeQuery() method on the download manager. Similar to querying a ContentProvider() method, we will receive an ICursor instance that we can use. With the cursor, we read the progress, status, any errors, and paths associated with a download.

Note

Information on a download is returned through an ICursor instance, similar to results from ContentProvider.

If we want to be notified when a download is complete, we can create a BroadcastReceiver instance that will respond to the ActionDownloadComplete broadcast. This broadcast will contain the ID of the download in the extras of the intent, which we can use to update our app.

See also

  • The Handling network state changes recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.159.10