i\'m developing an app where users are able to download different content packages. For the download process i am using the DownloadManager class. Thats working fine so far.
It turns out that the FileObserver
implementation on Marshmallow has a bug. As a result, FileObserver
will not report any modifications of a file downloaded by the download manager. (Older Android versions do not have this issue – it works fine on KitKat.) Source
For me, the following code (based on this answer) works well. I poll every second – I've tried halving that interval, but without any visible effect.
private static final int PROGRESS_DELAY = 1000;
Handler handler = new Handler();
private boolean isProgressCheckerRunning = false;
// when the first download starts
startProgressChecker();
// when the last download finishes or the Activity is destroyed
stopProgressChecker();
/**
* Checks download progress.
*/
private void checkProgress() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterByStatus(~(DownloadManager.STATUS_FAILED | DownloadManager.STATUS_SUCCESSFUL));
Cursor cursor = downloadManager.query(query);
if (!cursor.moveToFirst()) {
cursor.close();
return;
}
do {
long reference = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
long progress = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
// do whatever you need with the progress
} while (cursor.moveToNext());
cursor.close();
}
/**
* Starts watching download progress.
*
* This method is safe to call multiple times. Starting an already running progress checker is a no-op.
*/
private void startProgressChecker() {
if (!isProgressCheckerRunning) {
progressChecker.run();
isProgressCheckerRunning = true;
}
}
/**
* Stops watching download progress.
*/
private void stopProgressChecker() {
handler.removeCallbacks(progressChecker);
isProgressCheckerRunning = false;
}
/**
* Checks download progress and updates status, then re-schedules itself.
*/
private Runnable progressChecker = new Runnable() {
@Override
public void run() {
try {
checkProgress();
// manager reference not found. Commenting the code for compilation
//manager.refresh();
} finally {
handler.postDelayed(progressChecker, PROGRESS_DELAY);
}
}
};