Using ProgressBar with DownloadManager

android, android-download-manager, firebase-storage

Solution

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

Problem

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.

Original source

Related problems