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);
}
};
Related
There is a feature in ADM (Download Manager) that if the user touches a download link (not a web page), the ADM(Download Manager) will be appeared as an application that has the ability to download files.
What should I do that if the user touched a download link, my application will be appeared a an application that has the ability to download files?
DownloadData class
private long DownloadData (Uri uri, View v) {
long downloadReference;
// Create request for android download manager
downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
//Setting title of request
request.setTitle("Data Download");
//Setting description of request
request.setDescription("Android Data download using DownloadManager.");
//Set the local destination for the downloaded file to a path
//within the application's external files directory
if(v.getId() == R.id.DownloadMusic)
request.setDestinationInExternalFilesDir(MainActivity.this,
Environment.DIRECTORY_DOWNLOADS,"AndroidTutorialPoint.mp3");
else if(v.getId() == R.id.DownloadImage)
request.setDestinationInExternalFilesDir(MainActivity.this,
Environment.DIRECTORY_DOWNLOADS,"AndroidTutorialPoint.jpg");
//Enqueue download and save into referenceId
downloadReference = downloadManager.enqueue(request);
Button DownloadStatus = (Button) findViewById(R.id.DownloadStatus);
DownloadStatus.setEnabled(true);
Button CancelDownload = (Button) findViewById(R.id.CancelDownload);
CancelDownload.setEnabled(true);
return downloadReference;
}
Description of the above code:
downloadReference: It is a unique id that we will refer for specific download request.
request: Instance of DownloadManager will be created through getSystemService by passing
DOWNLOAD_SERVICE. A new request is generated in the next statement using DownloadManager.Request(uri).
setDestinationInExternalFilesDir: This will be used to save file in external downloads folder.
downloadManager.enqueue(request): Enqueue a new download corresponding to request. The download will start automatically once the download manager is ready to execute it and connectivity is available.
Source :https://www.codeproject.com/Articles/1112730/Android-Download-Manager-Tutorial-How-to-Download
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.
Hi I'm facing a little problem here. For updates of my App (that isn't available in Play Store) I download it via DownloadManager to the Donwload directoryof the device. The .apk file is on a ftp server.
After downloading I pop up a dialog if the user wants to install the update (not malicious or something, no root needed). Everything works fine except the user cancels this dialog and wants to "manually" install the apk by clicking on the downloaded file in the Download diretory. If so, I don't get the Package-Installer to choose to open the file. On some devices "HTML Viewer" is opened without a question. If I download the apk via QR-Code (direct link) from browser everything is fine, so I guess it's a failure coming with the DownloadManager.
How can I download a file from ftp with DownloadManager, so that it is recognized as .apk and I can install it from the download region?
Here's the code for downloading and installIntent:
String url = "http://www.test.xx/myApp.apk";
Uri mUri = Uri.parse(url);
DownloadManager.Request r = new DownloadManager.Request(mUri);
r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "myApp.apk");
r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager)activity.getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(r);
And on download receive:
#Override
public void onReceive(Context context, Intent intent) {
try {
Bundle extras = intent.getExtras();
long myDownloadID = DashboardActivity.this.mSharedPref.getLong(PreferenceIdentifier.DOWNLOAD_APK.toString(), 0);
mSharedPref.edit().remove(PreferenceIdentifier.DOWNLOAD_APK.toString()).commit();
long downloadCompletedId = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
DownloadManager.Query q = new DownloadManager.Query();
if (myDownloadID == downloadCompletedId) {
q.setFilterById(downloadCompletedId);
DownloadManager mManager = (DownloadManager) MyActivity.this.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor c = mManager.query(q);
if (c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
Intent promptInstall = new Intent(Intent.ACTION_VIEW);
promptInstall.setDataAndType(
Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/myApp.apk")),
"application/vnd.android.package-archive");
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(promptInstall);
}
}
c.close();
}
As you can see I did
promptInstall.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/myApp.apk")),
"application/vnd.android.package-archive");
I thought that would set the file type to apk so it is handles as one.
Hope I made my point clear, can anyone help?
Yeah, well... kinda stupid..
promptInstall.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/myApp.apk")),
"application/vnd.android.package-archive");
just affects the way android want to open the file..
DownloadManager.Request r = new DownloadManager.Request(mUri);
r.setMimeType("application/vnd.android.package-archive");
will do it...
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
}
}
};