问题
Android N has a new Cancel Button in the Download Manager Notification.
I would like to excecute some code in my app to stop a progressbar when the user presses this button. If any, which method is called?
Please also note that the Intent filter action DownloadManager.ACTION_NOTIFICATION_CLICKED is triggered only when the user clicks on the notification itself, not when he/she clicks of the Cancel button.
if_downloadManager = new IntentFilter();
if_downloadManager.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
if_downloadManager.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
br_downloadManager = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
....
}
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
// This code is not executed when the user presses the Cancel Button in the Download Manager Notification
}
}
};
Thanks in advance.
回答1:
I had the same problem in my app where I had to handle the Cancel button on the downloads notification and downloads deletion from the native Downloads app.
Turns out that if you register a receiver with the intent filter: DownloadManager.ACTION_DOWNLOAD_COMPLETE, it's always called when the cancel or downloads deletion is initiated.
So, How to differentiate between Download Complete and Download Deletion?
Well, it's quite simple:
- Get the Download Manager ID (
dmid
) of the canceled download from theIntent data
that is passed as an argument to thehandleReceive
function of yourBroadcastReceiver
. - Using that
dmid
query the DownloadManager for its status. - The DownloadManager would either return null for that
dmid
or the value forDownloadManager.STATUS_SUCCESSFUL
column would befalse
for the said download. - Once you know this, you can do whatever you want!
For reference you can see how I did it here:
- My Receiver's declaration in AndroidManifest.xml: https://github.com/edx/edx-app-android/blob/8a75d0dba6b8570956eac5c21c99ecd5020c81ae/OpenEdXMobile/AndroidManifest.xml#L265-L271
- My Reciever's actual code that handles this case: https://github.com/edx/edx-app-android/blob/d986a9ab64e7a0f999024035ec6fcbdb3428f613/OpenEdXMobile/src/main/java/org/edx/mobile/module/download/DownloadCompleteReceiver.java#L50-L62
回答2:
Malko, I did not find a solution but I am using the following workaround meanwhile. I use the Android Handler to run every 10 seconds resetProgressIfNoOngoingDMRequest() below :
public int numberOfOngoingDMRequest() {
cursor = downloadManager.query(new Query());
int res = cursor.getCount();
cursor.close();
return res;
}
public boolean resetProgressIfNoOngoingDMRequest() {
if (numberOfOngoingDMRequest() == 0) {
refreshUpdateAllButton(false);
resetEpisodesDownloadIds();
act.misc.notifyEpisodesDataSetChanged();
return true;
}
return false;
}
Not so nice but it does the job. And I do this only if the app is in the foreground.
回答3:
Another solution is use ContentObserver
.
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();
}
}
}
}
}
});
see the answer here
回答4:
I have solution very similar to MiaN KhaLiD. DownloadManager.ACTION_DOWNLOAD_COMPLETE is always receiver when "Cancel" is clicked. I do that in receiver:
Cursor cursor = downloadManager.query(query);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status;
try {
status = cursor.getInt(columnIndex);
KLog.d("download status = " + status);
} catch (CursorIndexOutOfBoundsException e) {
KLog.d("cancelled from notification");
return;
}
来源:https://stackoverflow.com/questions/42029895/android-n-download-manager-notification-cancel-button