Android推送通知:图标未显示在通知中,而是显示白色正方形

Android Push Notifications: Icon not displaying in notification, white square shown instead

我的应用程序生成了一个通知,但是未显示我为此通知设置的图标。 相反,我得到一个白色正方形。

我尝试过调整图标的png大小(尺寸720x720、66x66、44x44、22x22)。 奇怪的是,当使用较小的尺寸时,白色正方形较小。

我用谷歌搜索了这个问题,以及生成通知的正确方法,从我的阅读中我的代码应该是正确的。 可悲的是事情没有达到应有的状态。

我的手机是带有Android 5.1.1的Nexus 5。 模拟器,带Android 5.0.1的三星Galaxy s4和带Android 5.0.1的摩托罗拉Moto G(模拟器)也存在问题(我都借了,现在都没有)

通知代码如下,还有两个屏幕截图。 如果您需要更多信息,请随时提出要求。

谢谢你们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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 notification
notifications opened


原因:对于5.0 Lollipop,"通知图标必须完全为白色"。

If we solve 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.

目标SDK 21的解决方案

如果要支持棒棒糖材质图标,则为棒棒糖及更高版本制作透明图标。请参考以下内容:
https://design.google.com/icons/

请查看http://developer.android.com/design/style/iconography.html,我们将看到白色样式是通知在Android Lollipop中的显示方式。

在Lollipop中,Google还建议我们使用一种颜色,该颜色将显示在白色通知图标的后面。请参阅链接:https://developer.android.com/about/versions/android-5.0-changes.html

无论我们在哪里添加颜色
https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setColor(int)

低于和高于Lollipop OS版本的Notification Builder的实现为:

1
2
3
4
5
6
7
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);
}

注意:setColor仅在Lollipop中可用,并且仅影响图标的背景。

它将彻底解决您的问题!!


如果您使用的是Google Cloud Messaging,那么仅更改图标就无法解决此问题。例如,这将不起作用:

1
2
3
4
5
6
7
8
 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();

即使ic_notification是透明和白色的。还必须在清单元数据中定义它,如下所示:

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

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

元数据位于application标记下,以供参考。


我真的建议您遵循Google的设计指南:

表示"通知图标必须完全为白色。"


在Android Manifest中声明以下代码:

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

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

我希望这对您有用。


我们可以像下面这样:

创建一个通知构建器的新对象,并使用通知构建器对象调用setSmallIcon(),如下面的代码所示。

创建一个方法,在该方法中我们将检查要安装应用程序的操作系统版本。如果它低于Lolipop即API 21,则它将使用具有背景色的普通应用程序图标,否则它将使用没有任何背景的透明应用程序图标。因此,使用os version> = 21的设备将使用Notification builder类的方法setColor()设置图标的背景颜色。

样例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


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

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

在应用程序块的manifest.xml文件中添加此行


尝试这个

我遇到了同样的问题,我尝试了很多答案,但没有得到任何解决方案,最后我找到了解决问题的方法。

-制作带有透明背景的通知图标。应用程序的宽度和高度必须与以下尺寸相同,并将所有这些内容粘贴到您的项目中-> app-> src-> main-> res

  • MDPI 24 * 24

  • HDPI 36 * 36

  • XHDPI 48 * 48

  • XXHDPI 72 * 72

在上面之后,将此下面的行粘贴到onMessageReceived方法中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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());

不要忘记在清单文件中添加此代码

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

如果您想提供棒棒糖支持通知图标,请制作两种类型的通知图标:

  • 正常通知图标:适用于以下棒棒糖版本。
  • 带有透明背景的通知图标:适用于棒棒糖及以上版本。
  • 现在,基于操作系统版本,在运行时为通知生成器设置适当的图标:

    1
    2
    3
    4
    5
    6
    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);
    }

    终于,我有了解决这个问题的方法。

    仅当应用程序完全没有运行时,才会发生此问题。 (无论是在后台还是在前台)。当应用程序在前景或背景上运行时,通知图标会正确显示。(非白色正方形)

    因此,我们要设置的是后端API中的通知图标配置与前端相同。

    在前端,我们使用了React Native,对于推送通知,我们使用了react-native-fcm npm包。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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
       });
    });

    我们使用了fcm-push npm软件包,该软件包使用Node.js作为推送通知的后端,并按如下所示设置有效负载结构。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
      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"
      }
    }

    它基本上会搜索我们的Android系统中本地存储的notification_icon图像。


    通知是灰度的,如下所述。尽管其他人已经写过,但它们不是黑白的。您可能已经看到带有多种阴影的图标,例如网络强度条。

    在API 21(Lollipop 5.0)之前,颜色图标可以使用。您可以强制应用程序以API 20为目标,但这限制了应用程序可用的功能,因此不建议这样做。您可以测试正在运行的API级别,并适当设置颜色图标或灰度图标,但这可能不值得。在大多数情况下,最好使用灰度图标。

    图像具有四个通道,RGBA(红色/绿色/蓝色/ alpha)。对于通知图标,Android会忽略R,G和B通道。唯一重要的渠道是Alpha,也称为不透明度。使用编辑器设计图标,该编辑器可让您控制绘图颜色的Alpha值。

    Alpha值如何生成灰度图像:

    • Alpha = 0(透明)—这些像素是透明的,显示背景色。
    • Alpha = 255(不透明)—这些像素是白色的。
    • Alpha = 1 ... 254-这些像素正是您所期望的像素,提供了透明和白色之间的阴影。

    setColor进行更改:

    • 呼叫NotificationCompat.Builder.setColor(int argb)。从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.

      我对setColor的测试表明,不忽略Alpha组件。较高的Alpha值会使像素变白。较低的Alpha值会将像素变为通知区域中的背景颜色(在我的设备上为黑色),或在下拉通知中变为指定的颜色。


    我找到了一个链接,我们可以在其中生成自己的白色图标,

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

    打开此链接并上传您的ic_launcher或通知图标


    我已通过添加以下代码以实现清单来解决了该问题,

    1
    2
    3
    4
    5
    6
    7
        <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" />

    在Android Studio上创建的ic_stat_name上,右键单击res >> New >> Image Assets >> IconType(Notification)

    我还需要在服务器php端与通知有效负载一起执行的另一步骤

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $message = [
       "message" => [
           "notification" => [
               "body"  => $title ,
               "title" => $message
            ],

           "token" => $token,

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

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


        ]
    ];

    注意部分

    1
    2
    3
    4
    5
    6
       "android" => [
              "notification" => [
               "sound"  =>"default",
               "icon"  =>"ic_stat_name"
                ]
            ]

    图标名称为"icon" =>"ic_stat_name"的位置应与清单上的设置相同。


    (Android Studio 3.5)如果您是最新版本的Android Studio,则可以生成通知图像。右键单击您的res文件夹>新建>图像资产。然后,您将看到配置图像资产,如下图所示。将图标类型更改为通知图标。您的图像必须是白色和透明的。此配置映像资产将强制执行该规则。
    Configure Image Assets
    重要提示:如果希望将图标用于云/推送通知,则必须将元数据添加到应用程序标记下才能使用新创建的通知图标。

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

    解决此问题的要求:

  • 图像格式:32位PNG(带有Alpha)

  • 图片应该是透明的

  • 透明色指数:白色(FFFFFF)

  • 资料来源:http://gr1350.blogspot.com/2017/01/problem-with-setsmallicon.html


    要减少特定于SDK的版本,您只需执行以下操作:(将"#"替换为" 0x")

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


    如果SDK> = 23,请添加setLargeIcon

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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
    int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.colored_: R.drawable.white_tint_icon_for_lolipop_or_upper;

    当您想要保留彩色图标时-解决方法
    将颜色稍有不同的像素添加到图标中。就我而言,有一个带有阴影和灯光的黑色图标。添加深蓝色像素后,它将起作用。


    我在android 8.0上有类似的问题。尝试使用WHITE图标资源。我在尝试使用彩色图像作为图标时出现白色正方形,当我将其替换为白色图标时,它开始工作。