In Download manager, how to get status when its “cancel” from notification bar?

╄→гoц情女王★ 提交于 2019-12-10 17:41:39

问题


I am using download manger to download file in android. But in the case of when tap on "cancel" button from the notification bar , I am unable to get any broadcast.

I have find only two broadcast :

1.DownloadManager.ACTION_DOWNLOAD_COMPLETE 2.DownloadManager.ACTION_NOTIFICTION_CLICKED

Is there any broadcast by Download manager when its cancel ? If not then please give me any solution how to handle it ?


回答1:


DownloadManager will write information to database when it handle the user download task. So we can check the status of database to know if a task is canceled.

1. use the api from DownloadManager, polling status periodically

After you enqueue your download task, start the following thread to check.

private static class DownloadQueryThread extends Thread {

    private static final String TAG = "DownloadQueryThread";
    private final WeakReference<Context> context;
    private DownloadManager downloadManager;
    private final DownloadManager.Query downloadQuery;
    private boolean shouldStopQuery = false;
    private boolean downloadComplete = false;
    private static final Object LOCK = new Object();
    private final BroadcastReceiver downloadCompleteBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
                synchronized (LOCK) {
                    shouldStopQuery = true;
                    downloadComplete = true;
                }
            }
        }
    };

    /**
     * Create from context and download id
     * @param context the application context
     * @param queryId the download id from {@link DownloadManager#enqueue(DownloadManager.Request)}
     */
    public DownloadQueryThread(Context context, long queryId) {
        this.context = new WeakReference<>(context);
        this.downloadQuery = new DownloadManager.Query().setFilterById(queryId);
        this.downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
    }

    @Override
    public void run() {
        super.run();
        if (context.get() != null) {
            context.get().registerReceiver(downloadCompleteBroadcastReceiver,
                    new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
        }

        while (true) {

            if (downloadManager != null) {
                Cursor cursor = downloadManager.query(downloadQuery);
                if (cursor != null && cursor.moveToFirst()) {
                    Log.d(TAG, "download running");
                } else {
                    shouldStopQuery = true;
                }
            }

            synchronized (LOCK) {
                if (shouldStopQuery) {
                    if (downloadComplete) {
                        Log.d(TAG, "download complete");
                    } else {
                        Log.w(TAG, "download cancel");
                    }
                    break;
                }
            }

            try {
                sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (context.get() != null) {
            context.get().unregisterReceiver(downloadCompleteBroadcastReceiver);
        }
    }
}

2.use ContentObserver to get notified when database changed

The content uri for download manager should be content://downloads/my_downloads, we can monitor the changing of this database. When you start a download with a download id, a row will be created content://downloads/my_downloads/{downloadId}. We can check this cursor to know if this task is canceled or not. If the returned cursor is empty or null, no record found in database, this download task is canceled by user.

// get the download id from DownloadManager#enqueue
getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"),
            true, new ContentObserver(null) {
                @Override
                public void onChange(boolean selfChange, Uri uri) {
                    super.onChange(selfChange, uri);
                    if (uri.toString().matches(".*\\d+$")) {
                        long changedId = Long.parseLong(uri.getLastPathSegment());
                        if (changedId == downloadId[0]) {
                            Log.d(TAG, "onChange: " + uri.toString() + " " + changedId + " " + downloadId[0]);
                            Cursor cursor = null;
                            try {
                                cursor = getContentResolver().query(uri, null, null, null, null);
                                if (cursor != null && cursor.moveToFirst()) {
                                    Log.d(TAG, "onChange: running");
                                } else {
                                    Log.w(TAG, "onChange: cancel");
                                }
                            } finally {
                                if (cursor != null) {
                                    cursor.close();
                                }
                            }
                        }
                    }
                }
            });



回答2:


Another solution is to use a file observer at downloads directory

declaration of observer:

private FileObserver fileObserver = new DownloadObserver(
    Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS ).getAbsolutePath(), this);

When you want to start:

fileObserver.startWatching();

When you want to stop:

fileObserver.stopWatching();

The observer class:

public class DownloadObserver extends FileObserver {

public static final String TAG = "DownloadObserver";

Context context;

private static final int flags =
        FileObserver.CLOSE_WRITE
                | FileObserver.OPEN
                | FileObserver.MODIFY
                | FileObserver.DELETE
                | FileObserver.MOVED_FROM;

public DownloadObserver(String path, Context context) {
    super(path, flags);
    this.context = context;
}

@Override
public void onEvent(int event, String path) {

    if (path == null) {
        return;
    }

    if (event == FileObserver.OPEN || event == FileObserver.CLOSE_WRITE) {
        Log.d(TAG, "started or resumed: " + path);            
    } else if (event == FileObserver.DELETE) {
        Log.e(TAG, "File delete:" + path);
        //Here is your solution. Download was cancel from notification bar
    } else {
        //can be used to update download progress using DownloadManager.Query
    }
}}


来源:https://stackoverflow.com/questions/48248300/in-download-manager-how-to-get-status-when-its-cancel-from-notification-bar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!