In Download manager, how to get status when its "cancel" from notification bar?
Asked Answered
S

2

5

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 ?

Syncretism answered 14/1, 2018 at 9:40 Comment(2)
you should query the download manager to see what is the status of your download when you press the cancel button.Stairwell
Duplicate of stackoverflow.com/questions/42029895. See the other question where my answer has been accepted as the right solution.Godsend
M
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();
                                }
                            }
                        }
                    }
                }
            });
Marchal answered 15/1, 2018 at 2:13 Comment(0)
M
0

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
    }
}}
Margretmargreta answered 20/2, 2019 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.