215
votes

My app generates a notification, but the icon I set for that notification is not being displayed. Instead, I get a white square.

I have tried resizing the png of the icon (dimensions 720x720, 66x66, 44x44, 22x22). Curiously, when using smaller dimensions the white square is smaller.

I have googled this problem, as well as the correct way of generating notifications, and from what I've read my code should be correct. Sadly things are not as they should be.

My phone is a Nexus 5 with Android 5.1.1. The problem is also present on emulators, a Samsung Galaxy s4 with Android 5.0.1 and a Motorola Moto G with Android 5.0.1 (both of which I borrowed, and don't have right now)

The code for notifications follows, and two screenshots. If you require more information, please feel free to ask for it.

Thank you all.

@SuppressLint("NewApi") private void sendNotification(String msg, String title, String link, Bundle bundle) {
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
    resultIntent.putExtras(bundle);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            resultIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
    Notification notification;
    Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notificationsound);
    notification = new Notification.Builder(this)
                .setSmallIcon(R.drawable.lg_logo)
                .setContentTitle(title)
                .setStyle(new Notification.BigTextStyle().bigText(msg))
                .setAutoCancel(true)
                .setContentText(msg)
                .setContentIntent(contentIntent)
                .setSound(sound)
                .build();
    notificationManager.notify(0, notification);
}

without opening the notificationnotifications opened

21
did fix this issue ? still I am facing the same issue, in the top status bar still showing the white space for the notification if I add the transparent imageAngelJanniee
Yes, I fixed it by creating a transparent icon or targetting SDK version 20 or lower. If this doesn't fix it for you perhaps your similar problem has a different cause. I suggest setting target SDK version to 20 and checking if this changes anything. If it doesn't, not sure if this question can help you :(Blueriver

21 Answers

205
votes

Cause: For 5.0 Lollipop "Notification icons must be entirely white".

If we solve the white icon problem by setting target SDK to 20, our app will not target Android Lollipop, which means that we cannot use Lollipop-specific features.

Solution for target Sdk 21

If you want to support Lollipop Material Icons, then make transparent icons for Lollipop and the above version. Please refer to the following: https://design.google.com/icons/

Please look at http://developer.android.com/design/style/iconography.html, and we'll see that the white style is how notifications are meant to be displayed in Android Lollipop.

In Lollipop, Google also suggests that we use a color that will be displayed behind the white notification icon. Refer to the link: https://developer.android.com/about/versions/android-5.0-changes.html

Wherever we want to add Colors https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setColor(int)

Implementation of Notification Builder for below and above Lollipop OS version would be:

Notification notification = new NotificationCompat.Builder(this);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    notification.setSmallIcon(R.drawable.icon_transperent);
    notification.setColor(getResources().getColor(R.color.notification_color));
} else { 
    notification.setSmallIcon(R.drawable.icon);
} 

Note: setColor is only available in Lollipop and it only affects the background of the icon.

It will solve your problem completely!!

80
votes

If you are using Google Cloud Messaging, then this issue will not be solved by simply changing your icon. For example, this will not work:

 Notification notification  = new Notification.Builder(this)
                .setContentTitle(title)
                .setContentText(text)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentIntent(pIntent)
                .setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
                .setAutoCancel(true)
                .build();

Even if ic_notification is transparant and white. It must be also defined in the Manifest meta data, like so:

  <meta-data android:name="com.google.firebase.messaging.default_notification_icon"

            android:resource="@drawable/ic_notification" />

Meta-data goes under the application tag, for reference.

43
votes

I really suggest following Google's Design Guidelines:

which says "Notification icons must be entirely white."

37
votes

Declare this code in Android Manifest :

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" 

android:resource="@drawable/ic_stat_name" />

I hope this would be useful to you.

27
votes

(Android Studio 3.5) If you're using a recent version of Android Studio, you can generate your notification images. Right-click on your res folder > New > Image Asset. You will then see Configure Image Assets as shown in the image below. Change Icon Type to Notification Icons. Your images must be white and transparent. This Configure Image Assets will enforce that rule. Configure Image Assets Important: If you want the icons to be used for cloud/push notifications, you must add the meta-data under your application tag to use the newly created notification icons.

  <application>
      ...
      <meta-data android:name="com.google.firebase.messaging.default_notification_icon"
          android:resource="@drawable/ic_notification" />
13
votes
 <meta-data android:name="com.google.firebase.messaging.default_notification_icon"

        android:resource="@drawable/ic_notification" />

Add this line in the manifest.xml file in the application block.

10
votes

We can do like below:

Create a new object of notification builder and call setSmallIcon() using notification builder object like in below code.

Create a method in which we will check on which OS version we are installing our app . If it is below Lolipop i.e API 21 then it will take the normal app icon with background color else it will take the transparent app icon without any background. So the devices using os version >= 21 will set the background color of icon using method setColor() of Notification builder class.

Sample Code:

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);

notificationBuilder.setSmallIcon(getNotificationIcon(notificationBuilder));

private int getNotificationIcon(NotificationCompat.Builder notificationBuilder) {

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             int color = 0x008000;
             notificationBuilder.setColor(color);
             return R.drawable.app_icon_lolipop_above;

    } 
    return R.drawable.app_icon_lolipop_below;
}
10
votes

Try this

i was facing same issue i tried lot of anwers but didn't get any solutions,finally i found the way to solve my problem.

- make notification icon with transparent background .The app's width and height must be like below sizes and paste all these in your project->app->src->main->res

  • MDPI 24*24

  • HDPI 36*36

  • XHDPI 48*48

  • XXHDPI 72*72


after the above paste this below line in your onMessageReceived method


Intent intent = new Intent(this, News.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                    PendingIntent.FLAG_ONE_SHOT);
            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            {
                notificationBuilder.setSmallIcon(R.drawable.notify)
                                      //            .setContentTitle(title)
                            //                        .setContentText(message)
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setContentIntent(pendingIntent);
            } else
                {
                    notificationBuilder.setSmallIcon(R.drawable.notify)
                       //                                .setContentTitle(title)
                        //                        .setContentText(message)
                            .setAutoCancel(true)
                            .setSound(defaultSoundUri)
                            .setContentIntent(pendingIntent);
            }
            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(0, notificationBuilder.build());

Don't forget to add this code in manifest file

<meta-data 
android:name="com.google.firebase.messaging.default_notification_icon" 
android:resource="@drawable/app_icon" />
7
votes

If you wan to provide lollipop support notification icon then make two type notification icon :

  1. normal notification icon : for below lollipop version.
  2. notification icon with transparent background : for lollipop and above version.

Now set appropriate icon to notification builder at run time base on OS version :

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    mBuilder.setSmallIcon(R.drawable.ic_push_notification_transperent);
} else {
    mBuilder.setSmallIcon(R.drawable.ic_push_notification);
}
7
votes

Finally I've got the solution for this issue.

This issue occurs only when the app is not at all running. (neither in the background nor in the foreground). When the app runs on either foreground or background the notification icon is displayed properly.(not the white square)

So what we've to set is the same configuration for notification icon in Backend APIs as that of Frontend.

In the frontend we've used React Native and for push notification we've used react-native-fcm npm package.

FCM.on("notification", notif => {
   FCM.presentLocalNotification({
       body: notif.fcm.body,
       title: notif.fcm.title,
       big_text: notif.fcm.body,
       priority: "high",
       large_icon: "notification_icon", // notification icon
       icon: "notification_icon",
       show_in_foreground: true,
       color: '#8bc34b',
       vibrate: 300,
       lights: true,
       status: notif.status
   });
});

We've used fcm-push npm package using Node.js as a backend for push notification and set the payload structure as follows.

{
  to: '/topics/user', // required
  data: {
    id:212,
    message: 'test message',
    title: 'test title'
  },
  notification: {
    title: 'test title',
    body: 'test message',
    icon : 'notification_icon', // same name as mentioned in the front end
    color : '#8bc34b',
    click_action : "BROADCAST"
  }
}

What it basically searches for the notification_icon image stored locally in our Android system.

7
votes

I have resolved the problem by adding below code to manifest,

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_stat_name" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/black" />

where ic_stat_name created on Android Studio Right Click on res >> New >>Image Assets >> IconType(Notification)

And one more step I have to do on server php side with notification payload

$message = [
    "message" => [
        "notification" => [
            "body"  => $title , 
            "title" => $message
        ],

        "token" => $token,

    "android" => [
           "notification" => [
            "sound"  => "default",
            "icon"  => "ic_stat_name"
            ]
        ],

       "data" => [
            "title" => $title,
            "message" => $message
         ]


    ]
];

Note the section

    "android" => [
           "notification" => [
            "sound"  => "default",
            "icon"  => "ic_stat_name"
            ]
        ]

where icon name is "icon" => "ic_stat_name" should be the same set on manifest.

5
votes

Notifications are greyscale as explained below. They are not black-and-white, despite what others have written. You have probably seen icons with multiple shades, like network strength bars.

Prior to API 21 (Lollipop 5.0), colour icons work. You could force your application to target API 20, but that limits the features available to your application, so it is not recommended. You could test the running API level and set either a colour icon or a greyscale icon appropriately, but this is likely not worthwhile. In most cases, it is best to go with a greyscale icon.

Images have four channels, RGBA (red / green / blue / alpha). For notification icons, Android ignores the R, G, and B channels. The only channel that counts is Alpha, also known as opacity. Design your icon with an editor that gives you control over the Alpha value of your drawing colours.

How Alpha values generate a greyscale image:

  • Alpha = 0 (transparent) — These pixels are transparent, showing the background colour.
  • Alpha = 255 (opaque) — These pixels are white.
  • Alpha = 1 ... 254 — These pixels are exactly what you would expect, providing the shades between transparent and white.

Changing it up with setColor:

  • Call NotificationCompat.Builder.setColor(int argb). From the documentation for Notification.color:

    Accent color (an ARGB integer like the constants in Color) to be applied by the standard Style templates when presenting this notification. The current template design constructs a colorful header image by overlaying the icon image (stenciled in white) atop a field of this color. Alpha components are ignored.

    My testing with setColor shows that Alpha components are not ignored. Higher Alpha values turn a pixel white. Lower Alpha values turn a pixel to the background colour (black on my device) in the notification area, or to the specified colour in the pull-down notification.

4
votes

Requirements to fix this issue:

  1. Image Format: 32-bit PNG (with alpha)

  2. Image should be Transparent

  3. Transparency Color Index: White (FFFFFF)

Source: http://gr1350.blogspot.com/2017/01/problem-with-setsmallicon.html

4
votes

I found a link where we can generate our own white icon,

try this link to generate white icon of your launcher icon.

Open this Link and upload your ic_launcher or notification icon

3
votes

for customized local notification, in AndroidManifest.xml add following meta-data then it will work.

 <application
    android:name="xxxxxx"
        android:label="xxxxxx"
        android:icon="@mipmap/ic_launcher"
        
        >

       <meta-data
                android:name="your_apps_bundle_id.default_notification_icon"
                android:resource="@drawable/ic_notif" />

......
2
votes

I have similar issue on android 8.0. Try to use WHITE icon resource. I have white square when i'm trying to use colored image for icon, when i replace it to white icon, it's start work.

1
votes

You can use different icon for different versions. Simply set logic on your icon like this:

int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.colored_: R.drawable.white_tint_icon_for_lolipop_or_upper;
1
votes

For SDK >= 23, please add setLargeIcon

notification = new Notification.Builder(this)
            .setSmallIcon(R.drawable.ic_launcher)
            .setLargeIcon(context.getResources(), R.drawable.lg_logo))
            .setContentTitle(title)
            .setStyle(new Notification.BigTextStyle().bigText(msg))
            .setAutoCancel(true)
            .setContentText(msg)
            .setContentIntent(contentIntent)
            .setSound(sound)
            .build();
1
votes

To reduce SDK specific versions, you could simply do this: (replace '#' to '0x')

Notification notification = new NotificationCompat.Builder(this);
notification.setSmallIcon(R.drawable.icon_transperent);
notification.setColor(0x169AB9); //for color: #169AB9
0
votes

When you want keep colorful icon - Workaround
Add pixel with slightly different color into icon.
In my case a have black icon with shades and light. When added dark blue pixel it works.

0
votes

I just converted my png to a transparent png and then the icon was the same shape as the picture, but not the same color