Using ProgressBar with DownloadManager
Solution
Step 1. Declare the following variables in your class
// Indicate that we would like to update download progress
private static final int UPDATE_DOWNLOAD_PROGRESS = 1;
// Use a background thread to check the progress of downloading
private final ExecutorService executor = Executors.newFixedThreadPool(1);
// Use a hander to update progress bar on the main thread
private final Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
if (msg.what == UPDATE_DOWNLOAD_PROGRESS) {
int downloadProgress = msg.arg1;
// Update your progress bar here.
progressBar.setProgress(downloadProgress);
}
return true;
}
});
Step 2. Modify your downloadFile()
method
public void downloadFile(Context context, String fileName, String fileExtension, String destinationDirectory, String url) {
DownloadManager downloadManager = (DownloadManager) context.
getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalFilesDir(context, destinationDirectory, fileName + fileExtension);
long downloadId = downloadManager.enqueue(request);
// Run a task in a background thread to check download progress
executor.execute(new Runnable() {
@Override
public void run() {
int progress = 0;
boolean isDownloadFinished = false;
while (!isDownloadFinished) {
Cursor cursor = downloadManager.query(new DownloadManager.Query().setFilterById(downloadId));
if (cursor.moveToFirst()) {
int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (downloadStatus) {
case DownloadManager.STATUS_RUNNING:
long totalBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (totalBytes > 0) {
long downloadedBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
progress = (int) (downloadedBytes * 100 / totalBytes);
}
break;
case DownloadManager.STATUS_SUCCESSFUL:
progress = 100;
isDownloadFinished = true;
break;
case DownloadManager.STATUS_PAUSED:
case DownloadManager.STATUS_PENDING:
break;
case DownloadManager.STATUS_FAILED:
isDownloadFinished = true;
break;
}
Message message = Message.obtain();
message.what = UPDATE_DOWNLOAD_PROGRESS;
message.arg1 = progress;
mainHandler.sendMessage(message);
}
}
}
});
}
Note: Remember to release the executor and handler after downloading.
executor.shutdown();
mainHandler.removeCallbacksAndMessages(null);
Show Download progress inside activity using DownloadManager
You are dividing two integers:
final double dl_progress = (bytes_downloaded / bytes_total) * 100;
As bytes_downloaded
is less than bytes_total
, (bytes_downloaded / bytes_total)
will be 0, and your progress will therefore always be 0.
Change your calculation to
final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
to obtain the progress in whole (albeit floored) percentiles.
showing download progress in progress bar using DownloadManager
You have a Logic error, Your Query is out of the while loop where the UI is updated
private void startAppDownload() {
new Thread(new Runnable() {
@Override
public void run() {
boolean isDownloading = true;
int downloadStatus, totalBytesDownloaded, totalBytes;
while (isDownloading) {
DownloadManager.Query downloadQuery = new DownloadManager.Query();
downloadQuery.setFilterById(downloadID);
Cursor cursor = downloadManager.query(downloadQuery);
cursor.moveToFirst();
totalBytesDownloaded = cursor.getInt(
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
);
totalBytes = cursor.getInt(
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
);
downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if(downloadStatus == DownloadManager.STATUS_SUCCESSFUL) {
isDownloading = false;
break;;
}
final int downloadProgress = (int) ((double)totalBytesDownloaded / (double)totalBytes * 100f);
runOnUiThread(new Runnable() {
@Override
public void run() {
downloadProgressBar.setProgress(downloadProgress);
}
});
}
cursor.close();
}
}).start();
}
Progress Bar not showing with DownloadManager in android?
It doesn't work for you because your code related to tracking progress is inside a receiver which is called when the download is already finished. What you want to do is start a new thread which will poll the DownloadManager
for the information in a loop until it's finished:
final long downloadId = dm.enqueue(request);
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
int bytesDownloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytesTotal = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
break;
}
final int progress = (int) ((bytesDownloaded * 100l) / bytesTotal);
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setProgress(progress);
}
});
cursor.close();
}
}
}).start();
Download Manager Progress Not Visible in the Notification Area
Why This Happens in the first place?
The cause of the problem is the Android Download Manager's Notification was disabled in the settings. (It is the new default for my Galaxy S7 - SM930W8 which comes with the new Android N (7.0) Update)
The solution 1
- Go to the Settings > App
- In the options click 'Show System Apps'
- Find 'Download Manager' and open it
- Click 'Notifications' under App Settings
- Switch on Allow Notifications
After completing the above steps the above piece of code for downloading with notification working just fine.
The Solution 2
The above solution won't work with the general distribution of an application. We can't tell the users to do solution 1.
Adding your own small progress bar to show downloading percentage in your activity will give the user some idea that the file he/she requested is downloading.
Try to avoid notification because if the android download manager is giving the same notification then it is redundant. (default setting of show notification may vary device to device with respect to which ROM they are on)
So here is the code.
Uri uri = Uri.parse("file://" + destination);
url = "http:....."; //Valid File URL
//Set up download manager request
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Downloading " + file_name);
request.setTitle("My Downloader");
request.setDestinationUri(uri); //URI is valid
//Start the download
DownloadManager manager = (DownloadManager) getContext()
.getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
final int UPDATE_PROGRESS = 5020;
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==UPDATE_PROGRESS){
String downloaded = String.format("%.2f MB", (double)((msg.arg1)/1024)/1024);
String total = String.format("%.2f MB", (double) (msg.arg2)/1024)/1024);
String status = downloaded + " / " + total;
pDialog.setTitleText(status);
}
super.handleMessage(msg);
}
};
new Thread(new Runnable() {
@Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
//Post message to UI Thread
Message msg = handler.obtainMessage();
msg.what = UPDATE_PROGRESS;
//msg.obj = statusMessage(cursor);
msg.arg1 = bytes_downloaded;
msg.arg2 = bytes_total;
handler.sendMessage(msg);
cursor.close();
}
}
}).start();
The Solution 3
Adding request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
also helps as @kunal mentioned.
DownloadManager download progress not visible
private fun downloadPdf(fileName: String?, fileExtension: String?, destinationDirectory: String?, url: String?) {
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val uri = Uri.parse(url)
val request = DownloadManager.Request(uri)
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalPublicDir(destinationDirectory, fileName + fileExtension)
val downloadId = downloadManager.enqueue(request)
thread {
var downloading = true
while (downloading){
val query = DownloadManager.Query()
query.setFilterById(downloadId)
val cursor = downloadManager.query(query)
if(cursor.moveToFirst()){
val bytesDownloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
val bytesTotal = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
if(cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL){
downloading = false
}
val progress = ((bytesDownloaded * 100L)/bytesTotal).toInt()
runOnUiThread {
Log.i("pritishsawantprogress",progress.toString())
}
cursor.close()
}
}
}
}
Related Topics
How to Disable Proguard for Building My Android App
Which View Should Be Used for New Material Design Bottom Navigation
Android: Is Using Setcontentview Multiple Times Bad While Changing Layouts
Problem About SQLite Database, No Such Table
Handling Keepsynced() While on Background on Android and with Fcm
How to Get Meid and Imei Information Using Adb Commands on Android 5.0
My App Was Rejected by Instagram Basic Display API Review Due to Invalid Reasons
Best Way to Save Large Amount of Data Locally in Unity3D Android
Which Port and Protocol Does Google Cloud Messaging (Gcm) Use
Firebase Messaging Nosuchmethoderror.Zzur Exception
Android Facebook Authorization - Can Not Log in When Official Facebook App Is Installed
How to Change App Name Per Gradle Build Type
Room Cannot Verify the Data Integrity
Defining a Percentage Width for a Linearlayout
How to Import Maven Dependency in Android Studio/Intellij
How to Call One Android Application from Another Android Application