简体   繁体   English

Android 下载管理器进度

[英]Android DownloadManager Progress

i'm developing an app where users are able to download different content packages.我正在开发一个应用程序,用户可以在其中下载不同的内容包。 For the download process i am using the DownloadManager class.对于下载过程,我使用的是 DownloadManager 类。 Thats working fine so far.到目前为止工作正常。

My Question is how can i get the current progress of a running Download which was started with the DownloadManager.我的问题是如何获取使用 DownloadManager 启动的正在运行的下载的当前进度。 I know that there is the buildin Download Notification and so on.我知道有内置下载通知等等。 But for me it is necessary that i get the progress of the running download so i can use it to show the progress in a custom progressbar in my app.但对我来说,我有必要获得正在运行的下载进度,以便我可以使用它在我的应用程序的自定义进度条中显示进度。 So far i was not able to retrieve the progress.到目前为止,我无法检索进度。

Is it even possible or am i just blind and can't find the solution.它甚至可能还是我只是盲目而无法找到解决方案。

Hopefully someone can help me...希望有人可以帮助我...

I am looking for a better way of doing this also, but so far I am planning to just poll for progress every 1sec or so.我也在寻找一种更好的方法来做到这一点,但到目前为止,我计划每 1 秒左右轮询一次进度。

DownloadManager mgr = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
long id = mgr.enqueue(request);

DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(id);
Cursor cursor = mgr.query(q);
cursor.moveToFirst();
int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
cursor.close();

Edit:编辑:

A FileObserver can help with this. FileObserver可以帮助解决这个问题。 This is the skeleton of one I have put together to help keep track of which files our app has downloaded.这是我整理的框架,以帮助跟踪我们的应用程序下载了哪些文件。 Start it in an activity or service's onStart and stop it in onStop .在活动或服务的onStart启动它并在onStop停止它。 Combined with a manual synchronization of the state of things during onStart , this can give you a pretty complete picture of what's going on.结合onStart期间事物状态的手动同步,这可以让您对正在发生的事情有一个非常完整的了解。

For progress in particular, watching for the OPEN/CLOSE_WRITE events can help you decide when to start/stop polling the DownloadManager for updates.特别是对于进度,观察 OPEN/CLOSE_WRITE 事件可以帮助您决定何时开始/停止轮询 DownloadManager 以获取更新。

public class DownloadsObserver extends FileObserver {

    public static final String LOG_TAG = DownloadsObserver.class.getSimpleName();

    private static final int flags =
            FileObserver.CLOSE_WRITE
            | FileObserver.OPEN
            | FileObserver.MODIFY
            | FileObserver.DELETE
            | FileObserver.MOVED_FROM;
    // Received three of these after the delete event while deleting a video through a separate file manager app:
    // 01-16 15:52:27.627: D/APP(4316): DownloadsObserver: onEvent(1073741856, null)

    public DownloadsObserver(String path) {
        super(path, flags);
    }

    @Override
    public void onEvent(int event, String path) {
        Log.d(LOG_TAG, "onEvent(" + event + ", " + path + ")");

        if (path == null) {
            return;
        }

        switch (event) {
        case FileObserver.CLOSE_WRITE:
            // Download complete, or paused when wifi is disconnected. Possibly reported more than once in a row.
            // Useful for noticing when a download has been paused. For completions, register a receiver for 
            // DownloadManager.ACTION_DOWNLOAD_COMPLETE.
            break;
        case FileObserver.OPEN:
            // Called for both read and write modes.
            // Useful for noticing a download has been started or resumed.
            break;
        case FileObserver.DELETE:
        case FileObserver.MOVED_FROM:
            // These might come in handy for obvious reasons.
            break;
        case FileObserver.MODIFY:
            // Called very frequently while a download is ongoing (~1 per ms).
            // This could be used to trigger a progress update, but that should probably be done less often than this.
            break;
        }
    }
}

Usage would be something like this:用法是这样的:

public class MyActivity extends Activity {

    private FileObserver fileObserver = new DownloadsObserver(
            getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());

    @Override
    protected void onStart() {
        super.onStart();
        fileObserver.startWatching();
        syncUpDatabaseWithFileSystem();
    }

    @Override
    protected void onStop() {
        fileObserver.stopWatching();
        super.onStop();
    }
}

It turns out that the FileObserver implementation on Marshmallow has a bug.事实证明,Marshmallow 上的FileObserver实现有一个错误。 As a result, FileObserver will not report any modifications of a file downloaded by the download manager.因此, FileObserver不会报告下载管理器下载的文件的任何修改。 (Older Android versions do not have this issue – it works fine on KitKat.) Source (旧的 Android 版本没有这个问题——它在 KitKat 上运行良好。) 来源

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM