在Android KitKat中调用setGroup()时未显示通知

时间:2015-07-14 13:10:38

标签: java android notifications

我正在测试可堆叠通知(Stacking Notifications article)

我检测到在某些情况下,在运行android 4.X KitKat的设备中notify()调用后,通知未显示。

简单地说,问题是我创建了这个模拟通知的代码(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+中运行良好,首先显示第一个通知,单击第二个按钮时显示摘要,但在Android 4.X中,button1没有显示任何内容。

错误在哪里?

由于

2 个答案:

答案 0 :(得分:15)

对此的简短回答是,支持库不会自动支持显示KitKat设备上的堆叠通知。

由于你在这里要求启示,我的调查结果基于使用两台运行Android 4.4.2的设备进行测试。我也在使用AppCompat 23.1.1。

当您深入了解库的源代码时,您会发现当显示通知时,它会直接使用名为SideChannelNotificationManager的内容来显示通知。以下是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,你可以根据documentation实现它,但似乎你最好只是不在KitKat和之前的设备中使用分组通知。

答案 1 :(得分:2)

George的解决方案在技术上是正确的,但不是用户友好的,因为它基于NotificationListener,必须从用户手机安全设置中手动启用

我找到了这种工作方法,同时将setGroupSummary(true)设置为代表单个通知的那些方法,并通过指定通知类别的相同ID 通知每个人(例如消息而不是单个会话) 。 如果未应用特定分组样式,则通知将作为正常的非分组样式发布。 如果已过帐分组,则会替换任何单个通知,因为它们具有相同的 ID

Telegram for Android将此技术应用于KitKat及更低版本的分组通知。