我正在测试可堆叠通知(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没有显示任何内容。
错误在哪里?
由于
答案 0 :(得分:15)
对此的简短回答是,支持库不会自动支持显示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
,你可以根据documentation实现它,但似乎你最好只是不在KitKat和之前的设备中使用分组通知。
答案 1 :(得分:2)
George的解决方案在技术上是正确的,但不是用户友好的,因为它基于NotificationListener
,必须从用户手机安全设置中手动启用。
我找到了这种工作方法,同时将setGroupSummary(true)
设置为代表单个通知的那些方法,并通过指定通知类别的相同ID 通知每个人(例如消息而不是单个会话) 。
如果未应用特定分组样式,则通知将作为正常的非分组样式发布。
如果已过帐分组,则会替换任何单个通知,因为它们具有相同的 ID 。
Telegram for Android将此技术应用于KitKat及更低版本的分组通知。