12

DownloadManager appears to be the right choice for an app with lots of background downloads on a flaky mobile internet connection.

Using tutorial code found on the web, the app is able to request a download from the system's DM like so:

// in onCreate()
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

// in requestData()
Uri u = Uri.parse("http://server:8000/feed/data");
Request dreq = new Request(u);
dreq.setNotificationVisibility(Request.VISIBILITY_HIDDEN);
downloadID = dm.enqueue(dreq);

The URL in that code is a test server on a local computer. The URL works, the browser in Android emulator can retrieve the page and the server returns HTTP code 200 when my app requests that page via DownloadManager and the code quoted above.

This is the relevant code in the ACTION_DOWNLOAD_COMPLETE BroadcastReceiver which gets called when DM has retrieved the file.

Query q = new Query();
q.setFilterById(downloadID);
Log.i("handleData()", "Handling data");
Cursor c = dm.query(q);
if (c.moveToFirst()) {
  Log.i("handleData()", "Download ID: " + downloadID + " / " + c.getInt(c.getColumnIndex(DownloadManager.COLUMN_ID)));
  Log.i("handleData()", "Download Status: " + c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)));
  if (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
    String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
    Log.i("handleData()", "Download URI: " + uriString);
  } else if (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
    Log.i("handleData()", "Reason: " + c.getString(c.getColumnIndex(DownloadManager.COLUMN_REASON)));
  }
}

The strange result is this:

The DOWNLOAD_STATUS is 16 (or STATUS_FAILED), but the reason is "placeholder".

Why is that? Why does it fail when the server returned a 200 status code? And why is there no reason given by DownloadManager?

hez
  • 907
  • 1
  • 8
  • 20

1 Answers1

26

Answering myself here.

Here's the problem: COLUMN_REASON is not a string, but a number value.

Log.i("handleData()", "Reason: " + c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON)));

will return an actual error code that one can work with.

hez
  • 907
  • 1
  • 8
  • 20
  • where I can see what reason means what – Nick Jun 25 '13 at 08:34
  • 2
    There are several possible values listed in the [DownloadManager API doc](http://developer.android.com/reference/android/app/DownloadManager.html) - look for "Value of COLUMN_REASON" on that page. – hez Jun 25 '13 at 11:52
  • 1
    For the sake of those Googling this, it turns out that the ```Cursor``` supplied by the ```DownloadManager``` still reports the type (via ```getType()```) of ```COLUMN_REASON``` as ```String``` (and translates its value to ```placeholder```) when queried as such. Query the value as a number instead and the correct reason will be supplied. – technicalflaw Nov 19 '19 at 13:45