A fairly common operation in Android apps is the need to download content to the device. While it is easy enough to construct a network call to download the required content, there is also a built in way which can be particularly useful if the content being downloaded should also be shared with other apps, or stored in a publicly accessible location on the device. In this short series of articles we’ll take a look at DownloadManager which can solve many of the common problems in a really easy to use API.
Previously we looked at various setting that we can use to control individual downloads, but there is also some interesting stuff in DownloadManager itself, and in this article we’ll take a look at this.
Once important aspect of DownloadManager is that it has its own UI presence on the device. As well as the download notification, there is also the Downloads app which enables the user to view and manage downloaded files. This is particularly important if your app stores downloaded files outside of its own data area as these files will not automatically get deleted if the user uninstalls your app. If you perform a download using DownloadManager then the download will automatically get included in the Downloads app. Here we can see the results of some of my testing of the sample code for this series of posts:
However if you perform an independent download it is still possible to add it to the Downloads app by using the addCompletedDownload()
methods of DownloadManager. There are two variants of this method – one which was introduced in API 12 and a newer one (introduced in API24) which allows the inclusion of the original URI from which the content was downloaded and also the URI of the HTTP Referrer. One important thing to remember when using this mechanism to register independent downloads is that you must store the downloaded content in a publicly accessible location. You cannot store it in the apps private data area.
In the first article in this series we saw how, once a download has completed, we can query DownloadManager to obtain information such as the MIME type of the content. There are a number of other fields which we can interrogate to get detailed download status, and other information such as the total size of the downloaded content.
We also saw how we can call getUriForDownloadedFile()
to obtain a URI which we can use in an Intent (along with the MIME type) to launch an appropriate external viewer. This brings us on to an important point – the content itself was downloaded to the private data storage for the app and the URI that we saw had a schema of content
which means that it got exposed to the external app via a ContentProvider that was created for us by DownloadManager. This
It is worth considering where the appropriate place to store content is. Once again different apps will have different requirements so there is no single right answer. If the downloaded content is relatively small, and will only be consumed by the app itself then the private data area is ideal – this is the default behaviour. For larger content which is consumed only by the app itself, then the private data area on External storage is best – an important thing to remember is that this does not require the app to have WRITE_EXTERNAL_STORAGE
permission to save to the private External area. Finally, if the content should be publicly available (for example to Media Scanner so that images show up in the Gallery app) then they should be store to External public storage – you will need the WRITE_EXTERNAL_STORAGE
permission in order to do this.
To write to private external storage, call setDestinationInExternalFilesDir()
on the request object; and to write to public external storage then call setDestinationInExternalPublicDir()
instead having first requested and obtained WRITE_EXTERNAL_STORAGE
permission. I won’t go in to the code here, but there is an example of how to save to external public storage in the sample code – including the permission request.
That concludes our look at DownloadManager. The source code for this article is available here.
© 2016, Mark Allison. All rights reserved.
Copyright © 2016 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.
I think that in terms of API, I will always prefer to use my own implementation of a download manager.
Don’t you agree?