Android 7 中的通知 contentView 和 bigContentView 为空
Notification contentView and bigContentView are null in Android 7
我的应用程序的一部分包含一个自定义锁屏,它需要像正常 android 锁屏一样显示通知。
一切正常,直到 Android 6,我使用了 NotificationListenerService 来检索通知 contentView 和 bigContentView (RemoteViews)。我在我的自定义 RecyclerView 适配器上使用它们来创建一个通知列表,其中包含服务列出的相同通知:
//this is called by NotificationListenerService
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
AddNotification(sbn);
}
然后使用 StatusBarNotification 检索 contentView 和 bigContentView 并将它们应用到我的自定义回收视图列表视图中:
/**
* Add notification into recycleview
* @param sbn notification to add
*/
private void AddNotification(StatusBarNotification sbn)
{
Notification notification = sbn.getNotification();
if(notification==null) return;
if(notification.bigContentView!=null) {
//apply bigContentView to my recycleview list notification view
myListView.notificationview = notification.bigContentView.apply(myContext(), myNotificationLayout);
}
else if(notification.contentView!=null) {
//apply contentView to my recycleview list notification view
myListView.notificationview = notification.contentView.apply(myContext(), myNotificationLayout);
}
//notify recycleview of a new item inserted
notifyItemInserted(0);
}
Android 7 不再可能,因为从 Android N 开始(如 Android 文档中所述),contentView 和 bigContentView 可能为空(实际上他们是)。
这些非常有用,因为您可以复制通知视图,其中还可以包含一些复杂的操作控件(例如媒体播放器通知,例如 play/pause/stop 控件):
media player notification
是否可以在Android 7及以上版本中创建与原始通知内容相同的视图?
如何复制 RemoteView 行为?是否可以检索所有通知信息(图形、文本、图标、意图等)?
经过调查,无法检索通知的全部内容(即检索通知 Remoteviews),除非发送者使用自定义布局调用 setCustomContentView() and/or setCustomBigContentView()。
也就是说,此处唯一的解决方案是使用与原始通知相同的信息重新创建一个 Remoteview(或者两个,如果您希望同时拥有压缩版本和扩展版本)。为此,从 Bundle notification extras 中提取的信息将用于填充 XML 通知布局,您应该创建类似于以下内容的布局:
此外,您必须检查 extras Bundle 是否包含 Notification.EXTRA_TEMPLATE 键,如果是,请检查其样式。 XML 布局应复制不同类型的窗框(MediaStyle、InboxStyle、BigPictureStyle)并相应地填充所有字段。
我得到了更好的解决方案:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static RemoteViews getBigContentView(Context context, Notification notification)
{
if(notification.bigContentView != null)
return notification.bigContentView;
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return Notification.Builder.recoverBuilder(context, notification).createBigContentView();
else
return null;
}
public static RemoteViews getContentView(Context context, Notification notification)
{
if(notification.contentView != null)
return notification.contentView;
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return Notification.Builder.recoverBuilder(context, notification).createContentView();
else
return null;
}
每当您引用 Notification.contentView
时,只需调用 getContentView(...)
,并为 Notification.bigContentView
调用 getBigContentView(...)
。您的代码将支持 android nougat+ 和所有 android 版本。
修改后AddNotification
会变成这样:
/**
* Add notification into recycleview
*
* @param sbn notification to add
*/
private void AddNotification(StatusBarNotification sbn)
{
Notification notification = sbn.getNotification();
if (notification == null) return;
RemoteViews remoteViews = getBigContentView(myContext(), notification);
if(remoteViews == null)
remoteViews = getContentView(myContext(), notification);
if (remoteViews != null)
{
//apply bigContentView to my recycleview list notification view
myListView.notificationview = remoteViews.apply(myContext(), myNotificationLayout);
}
//notify recycleview of a new item inserted
notifyItemInserted(0);
}
我的应用程序的一部分包含一个自定义锁屏,它需要像正常 android 锁屏一样显示通知。
一切正常,直到 Android 6,我使用了 NotificationListenerService 来检索通知 contentView 和 bigContentView (RemoteViews)。我在我的自定义 RecyclerView 适配器上使用它们来创建一个通知列表,其中包含服务列出的相同通知:
//this is called by NotificationListenerService
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
AddNotification(sbn);
}
然后使用 StatusBarNotification 检索 contentView 和 bigContentView 并将它们应用到我的自定义回收视图列表视图中:
/**
* Add notification into recycleview
* @param sbn notification to add
*/
private void AddNotification(StatusBarNotification sbn)
{
Notification notification = sbn.getNotification();
if(notification==null) return;
if(notification.bigContentView!=null) {
//apply bigContentView to my recycleview list notification view
myListView.notificationview = notification.bigContentView.apply(myContext(), myNotificationLayout);
}
else if(notification.contentView!=null) {
//apply contentView to my recycleview list notification view
myListView.notificationview = notification.contentView.apply(myContext(), myNotificationLayout);
}
//notify recycleview of a new item inserted
notifyItemInserted(0);
}
Android 7 不再可能,因为从 Android N 开始(如 Android 文档中所述),contentView 和 bigContentView 可能为空(实际上他们是)。 这些非常有用,因为您可以复制通知视图,其中还可以包含一些复杂的操作控件(例如媒体播放器通知,例如 play/pause/stop 控件):
media player notification
是否可以在Android 7及以上版本中创建与原始通知内容相同的视图?
如何复制 RemoteView 行为?是否可以检索所有通知信息(图形、文本、图标、意图等)?
经过调查,无法检索通知的全部内容(即检索通知 Remoteviews),除非发送者使用自定义布局调用 setCustomContentView() and/or setCustomBigContentView()。
也就是说,此处唯一的解决方案是使用与原始通知相同的信息重新创建一个 Remoteview(或者两个,如果您希望同时拥有压缩版本和扩展版本)。为此,从 Bundle notification extras 中提取的信息将用于填充 XML 通知布局,您应该创建类似于以下内容的布局:
此外,您必须检查 extras Bundle 是否包含 Notification.EXTRA_TEMPLATE 键,如果是,请检查其样式。 XML 布局应复制不同类型的窗框(MediaStyle、InboxStyle、BigPictureStyle)并相应地填充所有字段。
我得到了更好的解决方案:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static RemoteViews getBigContentView(Context context, Notification notification)
{
if(notification.bigContentView != null)
return notification.bigContentView;
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return Notification.Builder.recoverBuilder(context, notification).createBigContentView();
else
return null;
}
public static RemoteViews getContentView(Context context, Notification notification)
{
if(notification.contentView != null)
return notification.contentView;
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return Notification.Builder.recoverBuilder(context, notification).createContentView();
else
return null;
}
每当您引用 Notification.contentView
时,只需调用 getContentView(...)
,并为 Notification.bigContentView
调用 getBigContentView(...)
。您的代码将支持 android nougat+ 和所有 android 版本。
修改后AddNotification
会变成这样:
/**
* Add notification into recycleview
*
* @param sbn notification to add
*/
private void AddNotification(StatusBarNotification sbn)
{
Notification notification = sbn.getNotification();
if (notification == null) return;
RemoteViews remoteViews = getBigContentView(myContext(), notification);
if(remoteViews == null)
remoteViews = getContentView(myContext(), notification);
if (remoteViews != null)
{
//apply bigContentView to my recycleview list notification view
myListView.notificationview = remoteViews.apply(myContext(), myNotificationLayout);
}
//notify recycleview of a new item inserted
notifyItemInserted(0);
}