Using ProgressBar with DownloadManager
Asked Answered
J

3

6

In my app, I use DownloadManager to download a file from Firebase.

import static android.os.Environment.DIRECTORY_DOWNLOADS;

public class Physics extends AppCompatActivity {
PDFView pdfView;
FirebaseStorage firebaseStorage;
StorageReference storageReference;
StorageReference ref;
File file;
File files;
ProgressBar progressBar;
private Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
    setContentView(R.layout.activity_physics1);

    pdfView = findViewById(R.id.pdfview);
    progressBar = (ProgressBar) findViewById(R.id.progressBar);


    Context mContext = getApplicationContext();
    String path = mContext.getFilesDir().getAbsolutePath() + "/storage/emulated/0/Android/data/com.impwala.impwala/files/Download/asd.nomedia";
    File file = new File("/storage/emulated/0/Android/data/com.impwala.impwala/files/Download/asd.nomedia");

    if (file.exists()) {
        files = new File("/storage/emulated/0/Android/data/com.impwala.impwala/files/Download/asd.nomedia");
        pdfView.fromFile(files).load();
    } else {
        if (haveNetwork()) {
            download();
        } else if (!haveNetwork()) {
            final Intent mainIntent = new Intent(Physics.this, Nointernet.class);
            Physics.this.startActivity(mainIntent);
            Physics.this.finish();
        }
    }
}

// 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;
    }

});

public boolean haveNetwork () {
    boolean have_WIFI = false;
    boolean have_MobileData = false;

    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
    NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();

    for (NetworkInfo info : networkInfos) {
        if (info.getTypeName().equalsIgnoreCase("WIFI"))
            if (info.isConnected())
                have_WIFI = true;
        if (info.getTypeName().equalsIgnoreCase("MOBILE"))
            if (info.isConnected())
                have_MobileData = true;
    }
    return have_MobileData || have_WIFI;
}

public void download () {

    storageReference = FirebaseStorage.getInstance().getReference();
    ref = storageReference.child("asd.pdf");

    ref.getDownloadUrl()
            .addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri) {
                    String url = uri.toString();
                    downloadFile(Physics.this, "asd", ".nomedia", DIRECTORY_DOWNLOADS, url); // Successfully downloaded data to local file
                    // ...
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    // Handle failed download
                    // ...
                }
            });
}

public void downloadFile (Context context, String fileName, String fileExtension, String destinationDirectory, String url)
    {
        final 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);

      final 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);


                }
            }
        }
    });
    executor.shutdown();
    mainHandler.removeCallbacksAndMessages(null);
}
}

I want to show a progress bar to indicate the download's progress but I don't know how to implement it.

I edited my code with suggestions from @Son Truong and have a progress bar in XML

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/gradient"
    tools:context=".Physics">

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:max="100"/>

    <com.github.barteksc.pdfviewer.PDFView
        android:id="@+id/pdfview"
        android:layout_width="match_parent"
        android:layout_height="478dp"
        android:layout_gravity="bottom"
        />

</FrameLayout>

But the progress bar is not starting at the start of download and doesn't finish after the download is done. Also, There is no text to show if how much percentage is completed.

Jeepers answered 6/12, 2020 at 4:51 Comment(3)
Does this answer your question? Android DownloadManager ProgressTobey
No. This doesn't solve my query. I am not understanding how you do it.Jeepers
If you still don't get it, then try my below solution.Tobey
T
6

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);
Tobey answered 6/12, 2020 at 5:52 Comment(10)
where to release executer and handler . And Download manager and Download ID are requiring to be final?Jeepers
You can release when downloadProgress is 100. It's ok to set DownloadManager and id to be final because after create we don't change it anymore.Tobey
I tried above code But progressbar not showing while downloadingJeepers
Can you update your code, I tried to download a 1MB/10MB/100MB file and it works well.Tobey
Yes, the file is downloading but the progress bar is not coming how do you use it.Jeepers
@AkshayRaut I assume there is a ProgressBar inside your activity/fragment layout. Look at the line progressBar.setProgress(downloadProgress); in my answer, just replace it with your progress bar instance.Tobey
I used same instance as of yours. And I updated my code.Jeepers
Can you share your activity_physics1 layout file. I need it to reproduce on my side to find root cause of this issue.Tobey
Let us continue this discussion in chat.Tobey
The progress bar shows well just when the URL from the HTTPS protocol, but the HTTP shows just 100% when it is completed.Sidwohl
T
0
  1. make a broadcast receiver:
        @SuppressLint({"Range", "LongLogTag"})
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d("UpdateAPk", intent.getAction());
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { }else {
                dm.remove(downloadId);
                context.unregisterReceiver(receiver);
                requestForSpecificPermission();
            } } };
  1. Call the broadcast receiver:

context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

  1. Show Progress bar as the download manager starts downloading the file:
        DownloadManager.Request request = new DownloadManager.Request(
                Uri.parse(appUrl));
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
        request.setDescription("v:" + " " + latestVersion);
        request.setTitle(context.getResources().getString(R.string.app_name));
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
        downloadApkID = dm.enqueue(request);
        progressDialog.dismissDialog();
        final android.app.ProgressDialog progressBarDialog = new android.app.ProgressDialog(activityContext, R.style.ProgressBarTheme);
        progressBarDialog.setIcon(R.drawable.apni_dukan_logo_large);
        progressBarDialog.setTitle("Apni Dukan Update");
        progressBarDialog.setProgressStyle(android.app.ProgressDialog.STYLE_HORIZONTAL);
        progressBarDialog.setProgress(0);
        progressBarDialog.setCancelable(false);
        progressBarDialog.show();
        new Thread(() -> {

            boolean downloading = true;
            while (downloading) {

                DownloadManager.Query q = new DownloadManager.Query();
                q.setFilterById(downloadApkID);
                Cursor cursor = dm.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;
                    progressBarDialog.dismiss();
                }

                final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);

                activityContext.runOnUiThread(() -> progressBarDialog.setProgress((int) dl_progress));
                cursor.close();
            }
        }).start();
    }```
Tedious answered 30/8, 2022 at 18:24 Comment(0)
C
-1

There is an error in the accepted answer. In each iteration of the loop, the cursor must be closed

...
mainHandler.sendMessage(message);
cursor.close();
Crypto answered 6/4, 2023 at 5:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.