Notification background in Android Lollipop is white. How can I change it?

I want to show a notification for a message in my app. In previous versions of Android everything is ok, but in Lollipop the notification background is white.
I used this XML code for my notification layout in layout_message_notification.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_messageNotification"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight=".2"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent">

        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:src="@drawable/message_icon"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight=".8"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent">

        <TextView
            android:id="@+id/textView_notification_title"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="right|center_vertical"
            android:layout_margin="15dp"/>

    </LinearLayout>

</LinearLayout>

My notification in lollipop is shown like this:
notification style in lollipop

  • Why GoogleMaterial.Icon does not have logout Icon in android library?
  • Building/using runtime generated layout XML in Android
  • How can I change default dialog button text color in android 5
  • Is possible set Expanded Notification as default in Big Text Notifications?
  • Add drop shadow effects to EditText Field
  • failed to find Build Tools revision 21.1.1 - sdk up to date
  • How can I make the notification background dark or transparent, like in previous versions of Android?

  • Validating IP in android
  • Knowing when Edit text is done being edited
  • GcmListenerService.onMessageReceived() not called
  • Loading html file to webview on android from assets folder using Android Studio
  • Roboto font for Android 4+?
  • Compiling C++ code (XCode) for iOS and Android. Is it real?
  • 3 Solutions collect form web for “Notification background in Android Lollipop is white. How can I change it?”

    Eventually, if you like to follow official material design specification

    Always use style resources for the text of a custom notification

    and use custom layout of your notifications, you maybe consider to not overriding default background, but change text style due to API version. You can achieve it by creating two resource style files and used them according to current API version:

    values-v21/notification_styles.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <!-- according to official recommendation custom notifications should has the same text style as default one-->
      <style name="NotificationHeader" parent="@android:style/TextAppearance.Material.Notification.Title" />
      <style name="NotificationContent" parent="@android:style/TextAppearance.Material.Notification.Line2" />
    </resources>
    

    and

    values/notification_styles.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <!-- according to official recommendation custom notifications should has the same text style as default one-->
      <style name="NotificationHeader" parent="@android:style/TextAppearance.StatusBar.EventContent.Title" />
      <style name="NotificationContent" parent="@android:style/TextAppearance.StatusBar.EventContent" />
    </resources>
    

    This answer describes a hacky method of changing of notification background color.
    Pay attention: this is an undocumented workaround; it is based on reflection and may be broken on custom firmwares; it is applicable to Android Lollipop and Marshmallow versions only; it will not work on Android N and higher versions. I would recommend to stick with the default color unless you have a serious reason to avoid it.

    WHY
    There is no legal way to set a background color for the custom notification. Google decided that notifications must be white or light gray depending on its priority according to Material Design. However, Google also made two exceptions to this rule:

    1. Notifications for older applications are displayed with black
      background;
    2. Notifications created with MediaStyle can be of ANY color.

    As a result of the second exception, such limitation looks illogical and unreasoned, and that is the only possible excuse why you still want to use a custom color instead of the one that is recommended (or forced?) by Google.

    WHAT’S INSIDE
    Lets look into BaseStatusBar to see how this limitation is imposed. The only place where the background color for the notification is calculated is applyColorsAndBackgrounds method.
    First branch of the if statement is for legacy applications. The only way to get here is to set the target SDK of your application below Build.VERSION_CODES.LOLLIPOP. The background will be turned black in this case.
    We are interested in the entry.row.setTintColor statement. To reach it, several checks should be passed, including the one contained within isMediaNotification method. Here they are:

    1. The notification must contain both regular and big views.
    2. The top level layout in both views must have com.android.internal.R.id.status_bar_latest_event_content as its ID.
    3. The big layout must contain a widget with com.android.internal.R.id.media_actions as its ID.

    HOW
    The most problematic are IDs as long as they are declared in the internal resources and cannot be accessed from the application’s layout XML.
    The second problem is that the RemoteViews used in the notification is just an ID of the layout resource within the application and cannot be constructed in the code. As a result, we cannot add layouts with IDs required to pass all the checks mentioned above.

    However, Google added the addView and removeAllViews methods into RemoteViews for their needs (they are used in the MediaStyle notification) and forgot to make them private.

    So, the final idea is simple:

    • build the notification based on the internal layout defined by Google (to pass the 2nd check)
    • remove everything with removeAllViews
    • add our custom layout with addView
    • special case for big view: add the layout defined by Google which contains media_actions to invisible view inside of our custom layout (to pass the 3rd check)

    Drawbacks:

    • inflating unused views (they are removed right after inflating)
    • complicated and deeper layout hierarchy

    SOLUTION
    Our custom big view must contain FrameLayout with android.R.id.empty as its ID. Actually, any ID may be used here, just make sure that you reference the same ID in code (see below).

    // We need theese ids to use internal Android resources
    int topId = Resources.getSystem().getIdentifier("status_bar_latest_event_content", "id", "android");
    int topBigLayout = Resources.getSystem().getIdentifier("notification_template_material_big_media_narrow", "layout", "android");
    int topSmallLayout = Resources.getSystem().getIdentifier("notification_template_material_media", "layout", "android");
    
    RemoteViews viewSmall = ...; // Create our custom view here
    RemoteViews viewBig = ...; // Create our custom big view here
    
    // This is invisible inner view - to have media_actions in hierarchy
    RemoteViews innerTopView = new RemoteViews("android", topBigLayout);
    viewBig.addView(android.R.id.empty, innerTopView);
    
    // This should be on top - we need status_bar_latest_event_content as top layout
    RemoteViews topBigView = new RemoteViews("android", topBigLayout);
    topBigView.removeAllViews(topId);
    topBigView.addView(topId, viewBig);
    
    // This should be on top - we need status_bar_latest_event_content as top layout
    RemoteViews topSmallView = new RemoteViews("android", topSmallLayout);
    topSmallView.removeAllViews(topId);
    topSmallView.addView(topId, viewSmall);
    
    Notification.Builder builder = new Notification.Builder(this);
    
    builder.setSmallIcon(R.drawable.ic_notification)
            .setTicker("Some text")
            .setColor(0xff000000) // The desired color!
            .setContent(topSmallView);
    
    Notification n = builder.build();
    n.bigContentView = topBigView;
    
    // Use our notification "n" here as usual
    

    It is possible to use another layout instead of notification_template_material_big_media_narrow on the top level to manipulate the height of the big view. Search for appropriate one here among notification_template_xxx.xml files. But do not forget about putting media_actions into hierarchy.

    This is the correct notifiction’s behavior.

    If you want to have a direct control on this aspect I suggest you to do the following:

    • Create an alternative version of layout_message_notification.xml inside the folder res/layout-v21

    • Make a slightly change on this new version by changing the outer layout’s background color:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/layout_messageNotification"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/gray">
    //...
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.