Нажатие на Android Notification Actions не закрывает ящик уведомлений

Я добавляю уведомление в системную панель с помощью библиотеки NotificationCompat. Это уведомление имеет две кнопки действий. Кроме того, AutoCancel() в уведомлении имеет значение true.

При нажатии кнопок действий система настроена на запуск IntentService который вызывает NotificationManager.cancel(NOTIFICATION_ID) а затем запускает действие в новой задаче.
Проблема в том, что, хотя этот вызов удаляет уведомление из трея, он не разрушает ящик. Вызываемая активность рисуется за ящиком.

Может ли кто-нибудь пролить свет на то, какой специальный код необходим для закрытия розыгрыша, кроме отмены уведомления?

Ответ 1

Если ваше действие выполнено в виде широковещательной рассылки или службы, но вы намерены свернуть лоток уведомлений, вы должны широковещать android.intent.action.CLOSE_SYSTEM_DIALOGS от вашего onReceive. Это приведет к ручному закрытию ящика.

Ответ 2

Я обнаружил, что когда вы используете кнопки действий в расширенных уведомлениях, вам приходится писать дополнительный код, и вы более ограничены.

До использования расширенных уведомлений действие по умолчанию в уведомлении загрузки файла состояло в том, чтобы запустить активность VIEW в файле. Цель VIEW была завернута намерением Chooser. Я не мог использовать ожидающее намерение для намерения Chooser непосредственно из уведомления, потому что Chooser выйдет из строя, если не будет активности для просмотра типа файла. Таким образом, у меня был BroadcastReceiver, который запустил бы намерение Chooser.

С расширенными уведомлениями я решил изменить уведомление о загрузке файлов, поэтому действие по умолчанию - показать активность сведений о файле, с кнопками действий для просмотра и отправки. Как отмечено пользователем2536953, запуск широковещательного приемника из уведомления не закрывает ящик уведомлений. Основываясь на его информации о том, что активность закрывает ящик, я изменил свой вещательный приемник на NotificationActivity без какого-либо пользовательского интерфейса.

Как указано в этом сообщении Как отклонить уведомление Android после того, как действие было нажато, еще одна проблема заключается в том, что вы должны вручную отменить свое уведомление, когда пользователь нажимает действие кнопка. Уведомление отменяется автоматически для действия по умолчанию. Я также добавил код в NotificationActivity, чтобы справиться с этим.

Создание расширенного уведомления с помощью кнопок вида и отправки:

    NotificationCompat.Builder builder = new NotificationCompat.Builder(m_context).setAutoCancel(true);

    final PendingIntent contentIntent = DownloadedFileIntentUtils.buildPendingItemDetailIntent(m_context, item);
        builder.setContentIntent(contentIntent);

    PendingIntent viewIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_VIEW,
                m_context.getString(R.string.action_open), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_open_with, m_context.getString(R.string.action_open), viewIntent);

    PendingIntent sendIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_SEND,
                m_context.getString(R.string.action_send), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_share, m_context.getString(R.string.action_send), sendIntent);

    builder.setTicker(title)
    .setContentTitle(title)
    .setContentText(text)
    .setSmallIcon(R.drawable.notification_download);
    .setStyle(new NotificationCompat.BigTextStyle().bigText(text));

    getNotificationManager().notify(id, builder.build());

Создание намерения начать действие с кнопок действия уведомления:

    public static PendingIntent buildNotificationActionIntent(Context context, String action, String actionTitle, Uri uri,
        String mimeType, int notificationId) {
    // Build the file action intent (e.g. VIEW or SEND) that we eventually want to start.
    final Intent fileIntent = buildFileActionIntent(action, actionTitle, uri, mimeType);

    // Build the intent to start the NotificationActivity.
    final Intent notificationIntent = new Intent(context, NotificationActivity.class);
    // This flag must be set on activities started from a notification.
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // Pass the file action and notification id to the NotificationActivity.
    notificationIntent.putExtra(Intent.EXTRA_INTENT, fileIntent);
    notificationIntent.putExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, notificationId);

    // Return a pending intent to pass to the notification manager.
    return PendingIntent.getActivity(context, s_intentCode.getAndIncrement(), notificationIntent, PendingIntent.FLAG_ONE_SHOT);
}

public static Intent buildFileActionIntent(String action, String actionTitle, 
        Uri uri, String mimeType) {
    Intent intent = new Intent(action);
    intent.addCategory(Intent.CATEGORY_DEFAULT);

    if (action.equals(Intent.ACTION_SEND)) {
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.setType(mimeType);
    } else {
        intent.setDataAndType(uri, mimeType);
    }

    intent.putExtra(Intent.EXTRA_TITLE, actionTitle);

    // Grant read permission on the file to other apps without declared permission.
    int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
    intent.setFlags(flags);

    return intent;
}

Активность уведомления без какого-либо интерфейса:

public class NotificationActivity extends Activity {
private final static Logger s_logger = LogUtil.getLogger(NotificationActivity.class);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = getIntent();

    // Cancel the notification that initiated this activity.
    // This is required when using the action buttons in expanded notifications.
    // While the default action automatically closes the notification, the
    // actions initiated by buttons do not.
    int notificationId = intent.getIntExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, -1);
    if (notificationId != -1) {
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(notificationId);
    }

    // If there is an activity to handle the action, start the file action.
    if (DownloadedFileIntentUtils.verifyActivityIsAvailable(this, fileActionIntent, false)) {
            fileActionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            DownloadedFileIntentUtils.startFileActionActivity(this, fileActionIntent);
    }

    // Finish activity.
    finish();
}

public static void startFileActionActivity(Context context, Intent fileActionIntent) {
    // Start chooser intent.
    Intent chooser = Intent.createChooser(fileActionIntent, fileActionIntent.getStringExtra(Intent.EXTRA_TITLE));

    // Copy the flags from fileActionIntent to chooser intent.
    // FileActionExecutor must set FLAG_ACTIVITY_NEW_TASK on the intent passed to startActivity
    // because the flag is required when starting an activity from a context that is not an activity.
    chooser.addFlags(fileActionIntent.getFlags());

    context.startActivity(chooser);
}

Не забудьте добавить NotificationActivity в AndroidManifest.xml.

Ответ 3

Пока я полностью понимаю, что ответ Сумяйоти должен быть правильным... это на самом деле не...

Я использую

Intent CR = new Intent(CRCODE); 
PendingIntent.getBroadcast(getApplicationContext(), MY_ID, CR, 0);

в макете удаленного просмотра для текущего уведомления...

Я могу заверить вас, что он не закрывает ящик, но убирает намерение и рисует активность за открытым ящиком, а также выполняет другие задачи, которые я назначил моему приемнику...

Я тестировал как getActivity, так и getService (ни один из них не будет работать в моих обстоятельствах, мне нужно запустить несколько намерений в Recieve), и оба они правильно закрывают ящик...

Я знаю, что это не ответ, но когда и если я найду его, я отчитаюсь, чтобы отредактировать это...

сумасшедшая мысль... возможно, деятельность, не имеющая представления контента, может быть вызвана как широковещательный приемник, который, по мере необходимости, запускал бы соответствующие намерения другим классам или приложениям...

сумасшедшая мысль, перечисленная выше, работает... начинайте работу с PendingIntent.getActivity и используйте ее для ретрансляции трансляций или других намерений, затем завершите себя... эффект не является прямым, но незаметным для конечного пользователя

Ответ 4

Система андроидов сворачивает ящик уведомлений для вас всякий раз, когда вы нажимаете на уведомление и запускаете действие или трансляцию. Я не думаю, что есть какой-либо программный способ закрыть ящик уведомлений вашим кодом. Я предлагаю вам проверить намерения, которые вы передаете строителю уведомлений, и убедиться, что им даны правильные ссылки. Я думаю, что что-то внутри диспетчера уведомлений android блокируется из-за намерения, которое вы предоставляете. До сих пор я не видел, чтобы ящик уведомлений оставался открытым после того, как действие было инициировано из уведомления. Просто интересно узнать, имеет ли ваша целевая деятельность полупрозрачная область, где видна предыдущая активность, если это тогда, я предлагаю вам сделать фон полностью непрозрачным (без прозрачной/полупрозрачной области). Может быть, это предотвратит запуск стартовой панели андроида для завершения последовательности останова и, таким образом, не позволяет запускать, чтобы закрыть ящик уведомлений для вас. Надеюсь, я смог тебе помочь. Все лучшее.

Ответ 5

попробуй это:

    NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(getApplicationContext().NOTIFICATION_SERVICE);
    Intent notificationIntent = new Intent(this.getBaseContext(), MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder mNotifyBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
            getApplicationContext())
            .setTicker(getApplicationContext().getText(R.string.app_name))
            .setContentTitle(getApplicationContext().getText(R.string.app_name))
            .setContentText(getApplicationContext().getText(R.string.text))
            .setSmallIcon(R.drawable.smallicon)
            .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setVibrate(new long[]{150, 300});
    mNotifyBuilder.build().flags |= Notification.FLAG_AUTO_CANCEL;
    notificationManager.notify(1, mNotifyBuilder.build());