Android downloading file through DownloadManager not working correctly - android

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.

Related

Android unable to open file after download

I am downloading a pdf file using DownloadManager class. It works fine on a Huawei GRA-L09 with android 5.0.1 but on my Nexus 6p with android 7.1.1 I experience the following behavior:
After the file is downloaded I try to open it via intent Action_View so it will be opened with pdf viewer. But when I try to open it I got an error that the file size is 0 and cannot be opened. If I wait about 10 seconds I am able to open the file.
This is the source code of DownloadManager:
DownloadManager dm = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir("/Download", "test.pdf");
long enqueue = dm.enqueue(request);
This is the source code of the BroadcastReceiver:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(enqueue);
Cursor cursor = null;
String uri = null;
String mime = null;
try {
cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
// process download
uri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
mime = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
openFile(Uri.parse(uri), mime);
}
}
};
private void openFile(final Uri fileLocation, final String mimeType) {
Intent objIntent = new Intent(Intent.ACTION_VIEW);
objIntent.setDataAndType(fileLocation, mimeType);
Log.d(Constants.TAG, "Downloaded file Uri: " + fileLocation.toString() + " mime:" + mimeType);
objIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent chooserIntent = Intent.createChooser(objIntent, getString(R.string.choose_application));
startActivity(chooserIntent);//Starting the pdf viewer
}
I tried opening it without the intent for pdf, just by pressing the notification icon on the status bar. The same thing happens, as if the file is locked or not downloaded yet.
UPDATE: On the Nexus device I get file size = 0 when i check file.length() after the download is completed. On the Huawei GRA-L09 the file size is 1882670.
So why do I get Download completed broadcast for a file with size 0?

Android download list of files with callback

I've got an Activity from which i need to download and save list of files. Files and names are stored in Map <String,String>. After downloading all files I need to call function in my Activity.
I've already have AsyncTask class which downloads and saves files and an interface which callbacks to Activity.
How can i pass Map<String,String> to Asynctask or maybe there is another solutions?
Thanks.
This is not something that is suitable for an AsyncTask. You should look into implementing a custom Service, probably an IntentService.
There's a very good tutorial at http://www.vogella.com/tutorials/AndroidServices/article.html
I would recommend using Android DownloadManager and a list of IDs
DownloadManager downloadmanager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse("http://www.example.com/myfile.mp3");
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setTitle("My File");
request.setDescription("Downloading");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setVisibleInDownloadsUi(false);
request.setDestinationUri(Uri.parse("file://" + folderName + "/myfile.mp3"));
mList_refid.add(downloadmanager.enqueue(request));
To setup a callback, use registerReceiver
mList_refid = new ArrayList<>();
mDownloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
if (mList_refid != null && mList_refid.contains(downloadId)) {
mList_refid.remove(downloadId); // File is downloaded, remove it from ID list.
}
} else
Log.e(LOG, "BroadcastReceiver on receive action not handled : " + action);
}
};
registerReceiver(mDownloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

Android DownloadManager never returns ERROR_FILE_ALREADY_EXISTS

I am using DonwloadManager in my project, in the official reference there is description about ERROR_FILE_ALREADY_EXISTS. The problem is that I never get this error while using the same URL and Destination URI. DownloadManager is always downloads the same file, just adds some number at the end of the file name so it will be different from the previous download.
The enqueue code is really simple and working great, except this weird thing that allows you to re-download already downloaded file:
Uri uri = Uri.parse(url);
Request request = new Request(uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE |
DownloadManager.Request.NETWORK_WIFI);
request.setVisibleInDownloadsUi(false);
Uri fileDestinationUri = Uri.parse("file://" + new File(destinationFilePath);
request.setDestinationUri(fileDestinationUri);
long downloadId = downloadManager.enqueue(request);
I have a BroadcastReciever which is listening to android.intent.action.DOWNLOAD_COMPLETE intent:
#Override
public void onReceive(Context context, Intent intent) {
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Query query = new Query();
query.setFilterById(downloadId);
Cursor cur = dm.query(query);
if (cur.moveToFirst()) {
int columnIndex = cur.getColumnIndex(DownloadManager.COLUMN_STATUS);
switch (cur.getInt(columnIndex)) {
case DownloadManager.STATUS_SUCCESSFUL:
Log.d(Settings.TAG_APP, "Download successfully completed.");
break;
case DownloadManager.STATUS_FAILED:
int columnReasonIndex = cur.getColumnIndex(DownloadManager.COLUMN_REASON);
Log.d(Settings.TAG_APP, "Download failed with error: " + cur.getInt(columnReasonIndex));
break;
}
}
cur.close();
cur = null;
}
I found another 2 questions that somehow connects to my question, but without answers as well :
Android - Overwrite files when downloading via Download Manager
How can i make download manager overwrite an exisiting file instead of renaming the file in android

Launch Adobe Reader in Android App

I have an Android app where I intercept a PDF file download event in the WebView, download it using the DownloadManager, and launch a new intent with the Adobe Reader to display the file. It works fine, except that when the Adobe Reader starts, it displays the following message prior to displaying the actual file:
Read-only document | To modify this document save a copy on your device.
Save | View Read-only
After I dismiss this prompt, the document gets displayed correctly. How can I get rid of the Read-only prompt?
Here is my code:
public class MyDownloadListener implements DownloadListener {
MainActivity activity;
BroadcastReceiver receiver;
DownloadManager downloadManager;
public MyDownloadListener(MainActivity a) {
activity = a;
downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(downloadId);
Cursor c = downloadManager.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_FILENAME));
File fileSrc = new File(uriString);
Intent intentPdf = new Intent(Intent.ACTION_VIEW);
intentPdf.setDataAndType(Uri.fromFile(fileSrc), "application/pdf");
intentPdf.setPackage("com.adobe.reader");
intentPdf.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intentPdf);
}
}
}
}
};
activity.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Request request = new Request(Uri.parse(url));
downloadManager.enqueue(request);
}
}
As per the official documentation of class DownloadManager.Request
This class contains all the information necessary to request a new
download. The URI is the only required parameter. Note that the
default download destination is a shared volume where the system might
delete your file if it needs to reclaim space for system use. If this
is a problem, use a location on external storage (see
setDestinationUri(Uri).
So default location is more of a cache location and system can delete the file if it require more space. So if you want to kep the file then you can use setDestinationUri to provide the path in the SD card..
And it looks like the default space does not allow any other thread/process other then the download manager to write file in that space, hence the read only message from the adobe reader..

Downloaded file from Android App not visible in Downloads directory

I am in process of developing an app wherein I am downloading pdf files from a remote server. I am so far successful in downloading the PDF files on my phone via the app. The problem that I am facing is that the downloaded file is not visible in the Downloads directory on my Galaxy Nexus. When I use the file manager app I can see the file there and it opens up real nice.
I tried using the following options in my code but none of them seems to solve my problem (both these options successfully download the file and its visible in the file manager) :
outFile = new File(Environment.getExternalStorageDirectory() + "/" + fileName);
And
outFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
Can someone please help me with some clues ? Any hint or clue will be of great help.
I was able to do it using the DownloadManager in the following way :
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request(
Uri.parse("http://"));
enqueue = dm.enqueue(request);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
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)) {
Toast.makeText(getApplicationContext(), "Download Complete!!!", Toast.LENGTH_LONG).show();
}
}
}
}
};
registerReceiver(receiver, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));

Categories

Resources