Подтвердить что ты не робот

Уведомление не отображается, когда setGroup() вызывается в Android KitKat

Я тестирую стекируемые уведомления (Stacking Notifications article).

Я обнаружил, что в некоторых случаях уведомления не отображаются после вызова notify() в устройствах, на которых запущена андроид 4.X KitKat.

Чтобы просто проблема, я создал этот код, который имитирует уведомление (button1) и второе уведомление с помощью сводки (button2)

private final static int NOTIFICATION_ID_A=6;
private final static int NOTIFICATION_ID_B = 7;
private final static int NOTIFICATION_ID_SUMMARY = 8;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showNotif(NOTIFICATION_ID_A,false);
        }
    });
    findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showNotif(NOTIFICATION_ID_B,false);
            showNotif(NOTIFICATION_ID_SUMMARY,true);
        }
    });
}

private void showNotif(int notificationId,boolean groupSummary) {
    CharSequence title="Title "+notificationId;
    CharSequence message="Message "+notificationId;
    NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(this);
    notifBuilder.setSmallIcon(R.drawable.icon_notifications);
    notifBuilder.setContentTitle(title);
    notifBuilder.setContentText(message);
    notifBuilder.setGroupSummary(groupSummary);
    notifBuilder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT));
    notifBuilder.setGroup("group_" + 1);
    NotificationManagerCompat.from(this).notify(notificationId, notifBuilder.build());
}

Идея - сначала нажать кнопку1, а затем кнопку2. Он отлично работает в Android 5.0 и показывает первый notif first и сводку при нажатии второй кнопки, но в Android 4.X кнопка 1 ничего не показывает.

Где ошибка?

Спасибо

4b9b3361

Ответ 1

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

Поскольку вы попросили просветить здесь, мои результаты основаны на тестировании с двумя устройствами под управлением Android 4.4.2. Я также использую AppCompat 23.1.1.

Когда вы вникнете в исходный код библиотеки, вы обнаружите, что, когда будет показано уведомление, он либо будет использовать что-то, называемое SideChannel, либо NotificationManager, чтобы показать уведомление. Ниже приведен метод NotificationManagerCompat.notify для ссылки, показывающий это:

public void notify(String tag, int id, Notification notification) {
    // MY COMMENT: true when the notification has the extra 
    // NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL set to true.
    if (useSideChannelForNotification(notification)) {
        pushSideChannelQueue(new NotifyTask(mContext.getPackageName(), id, tag, notification));
        // Cancel this notification in notification manager if it just transitioned to being
        // side channelled.
        IMPL.cancelNotification(mNotificationManager, tag, id);
    } else {
        // MY COMMENT: this calls notificationManager.notify(id, notification); in the base implementation
        IMPL.postNotification(mNotificationManager, tag, id, notification);
    }
}

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

Доказательство того, что боковой канал используется, когда группа установлена, находится в NotificationCompatKitKat.Builder, где вы увидите следующий код:

if (groupKey != null) {
    mExtras.putString(NotificationCompatJellybean.EXTRA_GROUP_KEY, groupKey);
    if (groupSummary) {
        mExtras.putBoolean(NotificationCompatJellybean.EXTRA_GROUP_SUMMARY, true);
    } else {
        mExtras.putBoolean(NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL, true);
    }
}

Все это не похоже на серьезную сделку, пока вы не посмотрите, что делает метод pushSideChannelQueue(...) при показе уведомления с помощью SideChannel.

В результате он ищет службу, которая может обрабатывать действие android.support.BIND_NOTIFICATION_SIDE_CHANNEL, по умолчанию это не так, поэтому метод просто возвращает. Это то, что вызывает уведомление, никогда не отображаться.

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

Ответ 2

Решение Джорджа технически правильно, но не является удобным для пользователя, поскольку оно основано на NotificationListener, который должен быть включен вручную из настройки безопасности телефона пользователем.

Я нахожу этот рабочий метод, устанавливаю setGroupSummary(true) также те, которые представляют одно уведомление и уведомляют всех с одним и тем же идентификатором, которые определяют категорию уведомления (например, сообщения вместо одиночного разговора). Если какой-либо конкретный стиль группировки не применяется, уведомление публикуется как обычный негруппированный. Если группа сгруппирована, она заменяет любое одно уведомление, потому что имеет все те же id.

Telegram для Android применяет этот метод для группировки уведомлений также на KitKat и ниже.