I'm developing a magazine app and I need to download one edition of the magazine to be available in offline mode. One edition may have 20 articles.
I'm using download manager to download the articles, enqueueing all of them, but I need a callback when finished to download all articles of one edition.
If I click to download two magazines at once, it'll enqueue all the articles of both magazines and I need that they be individual.
So far I have this:
mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
for (final Materia materia : materiasList) {
String url = materia.url;
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Baixando...");
request.setTitle(mEditionTitle + " - " + materia.titulo);
request.allowScanningByMediaScanner();
request.setDestinationInExternalFilesDir(mContext, "/editions/" + String.valueOf(mEditionId) + File.separator, String.valueOf(materia.id) + ".html");
// get download service and enqueue file
mDownloadManager.enqueue(request);
}
EDIT:
I'm running this manager from a service.
Not sure this is the best solution but you could query your download manager at regular interval and get all the in progress downloads. Then you parse the result and check if it is still downloading some items for a collection or if they are all downloaded.
Query the manager:
ArrayList<QueuedDownload> downloads = new ArrayList<>();
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query myDownloadQuery = new DownloadManager.Query();
myDownloadQuery.setFilterByStatus(DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_PENDING);
Cursor cursor = downloadManager.query(myDownloadQuery);
while (cursor.moveToNext()) {
// Parse each download
}
cursor.close();
Of course that should run on a background thread.
Related
I use firewall on my network and this network has just one Ip that allowed access. I want to download my apk file from special Ip but Download Manager adds to list as STATUS_PENDING. How can I download this file without VPN?
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(urlPath));
downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
downloadRequest.setAllowedOverRoaming(true);
downloadRequest.setAllowedOverMetered(true);
downloadRequest.setTitle("NetworkApp");
downloadRequest.setDescription("Downloading NetworkApp " + versionName);
downloadRequest.setVisibleInDownloadsUi(true);
downloadRequest.setDestinationInExternalFilesDir(context, null, "NetworkApp.apk");
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
long downloadId = downloadManager.enqueue(downloadRequest);
Android Api:28
I have an Android app that has a feature of downloading files. After using the app for some time, downloading files not working.
I came to know after some research, after a clear cache of download manager of the system, downloading files work completely without any issue.
That means this solution works perfectly. But that doesn't mean application users have to do that to use the app. So I want to do that using code.
I need any solution that can clear the cache of Download Manager of the system using the code.
Here it is template code for downloading:
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
context.registerReceiver(downloadReceiver, filter);
downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle(savedFileName);
//Set a description of this download, to be displayed in notifications (if enabled)
//equest.setDescription("Android Data download using DownloadManager.");
//Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalPublicDir(download_path, savedFileName);
//Set visible and shows in the notifications while in progress and after completion.
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//Enqueue a new download and same the referenceId
downloadReference = downloadManager.enqueue(request);
// receiver
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadReference);
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
checkStatus(c);
}
};
I am downloading multiple file same time with download manager. but my problem is download manager start download all files with same time i need to start download file one by one in queue means first item download first than all one by one.
DownloadManager.Java
if(downloaddata.size()>0){
for(int i=0;i<downloaddata.size();i++){
downloadFiles(downloaddata.get(i).getFile_id(),downloaddata.get(i).getFile_url(),"OTHER");
}
}
public void downloadFiles(String myid,String myurl,String type){
createFolder();
String fileName = URLUtil.guessFileName(myurl, null, null);
Uri uri=Uri.parse(myurl);
request=new DownloadManager.Request(uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
request.setTitle(myid);
request.setMimeType(type);
request.setDestinationInExternalPublicDir("/peakmedia",fileName); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
downloadReference=downloadManager.enqueue(request);
downloadlist.add(downloadReference);
}
DownloadManager broadcasts ACTION_DOWNLOAD_COMPLETE, so you can just request the next file to download when the BroadcastReceiver receives success for previous file.
I'm trying to download files thru DownloadManager, it works perfectly on most of the phones (Nexus family, S3, etc) but on Galaxy S2 for some reason the download works, but the name of the file is set wrong and when I try to open it (either from notification, either downloads app) it says that the file cannot be opened, even for files like jpeg, gif, png, etc.
Here is the code:
DownloadManager downloadManager = (DownloadManager) service
.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request downloadReq = new DownloadManager.Request(
Uri.parse(URL));
downloadReq
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE);
downloadReq.allowScanningByMediaScanner();
downloadReq.setMimeType(attachment.mimeType);
downloadReq.setTitle(attachment.fileName);
downloadReq.setDescription("attachment");
downloadReq.setDestinationInExternalFilesDir(service,
Environment.DIRECTORY_DOWNLOADS, "");
downloadReq
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE
| DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
downloadIDs.add(downloadManager.enqueue(downloadReq));
Also please note that all the URLs are https, and the phone's android version is 4.1.2
Any idea?
Many Thanks!
Update: if I add the file name in this call:
downloadReq.setDestinationInExternalFilesDir(service,
Environment.DIRECTORY_DOWNLOADS, attachment.fileName);
the good name is displayed in the notification center.
You should register yourself to receive a broadcast when the file download is complete. Over there you can also grab the filename. This will need some changes to the code:
Retain the ID returned from enqueue call:
long enqueue = downloadManager.enqueue(downloadReq);
Register a receiver to get the broadcast:
getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
declare the receiver:
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
return;
}
context.getApplicationContext().unregisterReceiver(receiver);
Query query = new Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
Log.i(TAG, "downloaded file " + uriString);
} else {
Log.i(TAG, "download failed " + c.getInt(columnIndex));
}
}
}
};
Assuming a filename for download is not good practice. If you download it again without removing the previous one it will automatically get a suffix.
I am using Android DownloadManger System Service for downloading some files in following way
dwnId = mgr.enqueue(new DownloadManager.Request(serveruri)
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |
DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(getAlbumName())
.setDescription(getTrackName())
.setDestinationUri(deviceUri)
.setShowRunningNotification(true));
where mgr is Download Manager instance, dwnId is unique ID returned. I am also registering for ACTION_DOWNLOAD_COMPLETE
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
and in the onDownloadComplete BroadcastReceiver's onReceive() method I am getting download Id like
Long dwnId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
After that I am querying Download Manager for Download status
Cursor c = downloadManager.query(new DownloadManager.Query().setFilterById(dwnId)); c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
for DownloadManager.STATUS_* constants.
The problem is I am receiving the same downId twice (means onReceive method is called twice), once with DownloadManager.STATUS_SUCCESSFUL status and once with DownloadManager.STATUS_FAILED status for same dwnId. I am issuing request to download some 10 files at a time and but on device download manager it is showing the download count as some 12 or 13 in the notification bar top left means. I think that Download manager has some problem in downloading files and resumed or automatically restarted to download the same file again. Thats why there is a difference between the files count I requested to download and actual number in download queue. Because of this only I am getting same DownloadId complete action twice. If this is true, how to restrict it. Am I wrong what might be the reason for count difference between what I requested to actual download? Why is the broadcast receiver receiving the same download Id twice. Can anybody please let me know?
Thanks In Advance...
This is a reported bug see: http://code.google.com/p/android/issues/detail?id=18462
The way around I found is to verify if the download was a success, if not ditch the intent or re-queue the file if it was never downloaded...
Lost a couple of hours figuring that one :(
** Edit: adding code example **
/**
* Check if download was valid, see issue
* http://code.google.com/p/android/issues/detail?id=18462
* #param long1
* #return
*/
private boolean validDownload(long downloadId) {
Log.d(TAG,"Checking download status for id: " + downloadId);
//Verify if download is a success
Cursor c= dMgr.query(new DownloadManager.Query().setFilterById(downloadId));
if(c.moveToFirst()){
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if(status == DownloadManager.STATUS_SUCCESSFUL){
return true; //Download is valid, celebrate
}else{
int reason = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
Log.d(TAG, "Download not correct, status [" + status + "] reason [" + reason + "]");
return false;
}
}
return false;
}
For complete code see : https://github.com/flegare/JAV387_LaboWidget/blob/master/src/com/mobidroid/widgetfact/service/FactService.java
A simple way to download your files, See download progress in notification bar and even open your file when it complete to download by just clicking it in the notification bar.
Just call this method and pass your filename and download url
public void downloadFile(String name, String url){
//download link
downloadUri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);
//allow download to take place over wifi, mobile network and roaming
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE ).setAllowedOverRoaming(true);
request.setAllowedOverRoaming(false);
//name to show while downloading
request.setTitle(name);
//description to show while downloading
request.setDescription("Downloading " + name);
//show on navigation
request.setVisibleInDownloadsUi(true);
//download path
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS.toString(), "/" + name);
//file open when item on navigation is clicked
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
long downloadId = downloadManager.enqueue(request);
}
Output
You can learn more here
You can also add boolean or number, condition under Broadcast Receiver to done specific work after the completion of each download task.
As like
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadID == id) {
//firstDownload is a boolean variable and assign each downloadManager as true or false
if (firstDownload) {
//First task downlaoded
} else {
//Second task downloaded
}
}
};