I'm developing an Android app where I use DownloadManager to download files. It's able to successfully download certain files (eg. JPEG, MP3), but it's unsuccessful for others (eg. PDF). I'm not certain it's related to file type. I registered a BroadcastReceiver to help debug the issue. On the onReceive() callback, I query the DownloadManager to find the reason for the failure but it just gives a "400", which is not a documented reason.
Here is how I use DownloadManager:
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(url);
request.setTitle(filename);
request.setDestinationInExternalPublicDir(folder, filename);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
manager.enqueue(request);
On DownloadManager.STATUS_FAILED, here is my debugging code:
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = manager.query(query);
if(cursor.moveToFirst()){
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
Log.e("App", reason);
// the value of reason is 400 which is not a valid DownloadManager.ERROR_*
}
The value of reason should be one of the constants DownloadManager.ERROR_* but 400 is not. Same thing happens on two devices: Galaxy Nexus (v4.3) & Nexus 9 (v5.1). I tested the URL on the phone's browser and confirmed that works outside the app. Does anyone have any idea what's happening? Any help would be appreciated.
Thanks
EDITED: The file I'm trying to download has a space in the filename. I did a few quick experiments: removing spaces from files that didn't work, adding space to file that previously did work. It appears it might be related to the filename containing space.
EDITED: This is what I did to fix the problem. I had to encode the URL on the server (the URL is part of a json response so I changed the response)
url = URLEncoder.encode(url, "utf-8")
This 400 reason is HTTP error. Quoting docs:
Provides more detail on the status of the download. Its meaning depends on the value of COLUMN_STATUS. When COLUMN_STATUS is STATUS_FAILED, this indicates the type of error that occurred. If an HTTP error occurred, this will hold the HTTP status code as defined in RFC 2616. Otherwise, it will hold one of the ERROR_* constants. [...]
https://developer.android.com/reference/android/app/DownloadManager.html#COLUMN_REASON
And this HTTP error means
400 Bad Request The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
If you get other HTTP errors, consult this page for their meaning: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error