3

Part of my application consists in a custom lockscreen which needs to show notifications as normal android lockscreen does.

Everything works fine until Android 6, I used a NotificationListenerService to retrieve notification contentView and bigContentView (RemoteViews). I use them on my custom RecyclerView adapter to create a notification list with the same notifications listed by the service:

//this is called by NotificationListenerService
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
    AddNotification(sbn);
}

then use the StatusBarNotification to retrieve contentView and bigContentView and apply them in my custom recycleview list views:

/**
* 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);
}

This is no longer possible with Android 7 because starting with Android N (as stated in Android documentation), contentView and bigContentView could be null (actually they are). those were extremely useful beacuse you could replicate notification views which could also contain some complex action controls (such as media player notifications, with play/pause/stop controls for example):

media player notification

Is it possible in Android 7 and above to create a view with the same content of the original notification?

How do I replicate the RemoteView behaviour? Is it possible to retrieve all the notifications information (graphic, text, icons, intents, etc)?

target33
  • 78
  • 9

2 Answers2

3

I got a better solution:

@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;
}

Whenever you reference Notification.contentView, just call getContentView(...) instead, and getBigContentView(...) for Notification.bigContentView. Your code will support android nougat+, and all android versions.

After modification, AddNotification will be like this:

/**
 * 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);
}
Run
  • 2,148
  • 2
  • 12
  • 29
  • I spent almost a week trying to find a solution for this, and then a month to create an extractor class to recreate all different kinds of notification from notification extras info. So, even with delay, God bless you! recoverBuilder.. Damn android documentation... – target33 Sep 18 '18 at 12:40
  • Unfortunately after some research and testing, I found this method is not reliable 100%. On MIUI 10 phones (Xiaomi for example) all the notifications are corrupted (multiple lines of text on the same line, or notifications with reply buttons which cover all notification area) – target33 Nov 15 '18 at 10:58
2

After investigating, there's no way to retrieve the whole content of a notification (i.e. retrieve notification Remoteviews), unless the sender has used a custom layout invoking setCustomContentView() and/or setCustomBigContentView().

That said, the only solution here is to recreate a Remoteview (or two if you want to have both compact and expanded versions) with the same information as the original notification. To do so, information extracted from Bundle notification extras will be used to populate a XML notification layout you should create similar to the following:

Android N notification design

Also, you must check if the extras Bundle contains the Notification.EXTRA_TEMPLATE key and if so, check for its style. The XML layout should replicate the different types of stiles (MediaStyle, InboxStyle, BigPictureStyle) and populate all fields accordingly.

target33
  • 78
  • 9