Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are https downloads pausing with PAUSED_WAITING_TO_RETRY?

I'm using the DownloadManager service in Android to download files over https URLs, such as https://www.antennahouse.com/XSLsample/pdf/sample-link_1.pdf. The files are not (currently) password protected, in case that makes any difference.

Once I enqueue a download request, the DownloadManager starts the download, but it seems to hang. When I check the status, I get

COLUMN_BYTES_DOWNLOADED_SO_FAR: 0
COLUMN_STATUS: 4
COLUMN_REASON: 1

COLUMN_STATUS 4 is STATUS_PAUSED, "when the download is waiting to retry or resume."

COLUMN_REASON 1 is PAUSED_WAITING_TO_RETRY, "when the download is paused because some network error occurred and the download manager is waiting before retrying the request." But there doesn't seem to be a way to determine what network error occurred. The download never successfully completes.

I've checked the logcat monitor for related warnings and errors, but found nothing.

I've tried this with multiple different servers, both in-house and public, with the same result.

There is no obvious network problem: the Wi-Fi connection is up, and downloads using http:// work just fine: the file is downloaded promptly and appears in the filesystem at the specified destination.

In the case of https downloads, our server logs show that the files are being successfully served from the server's point of view. Testing the same https URLs in a browser on a laptop result in successful download of the files, without any obvious problems or extra negotiations showing up in the developer tools network panel.

My code (summarized):

sManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request req = new DownloadManager.Request(sourceURI);
final Uri destinationUri = Uri.fromFile(destinationFile);
req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
            | DownloadManager.Request.NETWORK_MOBILE)
        .setDestinationUri(destinationUri)
        .setMimeType(...);

long id = sManager.enqueue(req);

Summary: An https download started via DownloadManager hangs indefinitely, while the same https download works fine in a browser, and plain http downloads work fine with the same app using DownloadManager. The best clue I have is that PAUSED_WAITING_TO_RETRY indicates "some network error occurred." How can I determine what the network error is?

like image 934
LarsH Avatar asked Jan 02 '17 16:01

LarsH


People also ask

Why is my download being paused?

Restart your phone and try downloading a file. If the issue continues, tap on Clear data or Clear storage depending on the option available on your phone instead of Clear cache. On Samsung phones, you might find this option inside Manage storage. Then, restart your phone.

What is download manager on my Android phone?

The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file.

Where is download manager in vivo?

Open File Manager/My Files/Files (whichever is present on your phone) and tap on Download History.


Video Answer


1 Answers

The proximate cause seems to be a CertificateException: CertPathValidatorException: Trust anchor for certification path not found. I found this out by using an HttpURLConnection directly (thanks to @CommonsWare for the suggestion) instead of the DownloadManager, which gave more direct access to exceptions. (This was true in the case of our in-house server. It does not seem to be the case with the sample URL I mentioned, which seemed to be having the same problem with DownloadManager ... but maybe that same problem had a different cause.)

The root CA (in all cases) is "AddTrust External CA Root", which is present in the list of trusted CAs on the device, under Settings > Security > Trusted credentials. So if this is a trusted CA root, why is there a "Trust anchor for certification path not found" exception?

It looks like there is an intermediate CA not being included in the chain served by the server, as described here. In fact, using openssl s_client -connect to check the CA chain confirms that the intermediate CA's are not included. The Android doc article suggests two possible solutions: include the intermediate CA's in the server chain, or explicitly trust them in the app by creating a special TrustManager. I hope to do the former.

like image 171
LarsH Avatar answered Sep 17 '22 08:09

LarsH