【问题标题】:Notification Icon with the new Firebase Cloud Messaging system带有新 Firebase 云消息传递系统的通知图标
【发布时间】:2016-09-16 10:36:08
【问题描述】:

昨天,Google 在 Google I/O 上展示了基于新 Firebase 的新通知系统。我用 Github 上的示例尝试了这个新的 FCM(Firebase Cloud Messaging)。

通知的图标始终是 ic_launcher,尽管我已经声明了一个特定的可绘制对象

为什么? 下面是处理消息的官方代码

public class AppFirebaseMessagingService extends FirebaseMessagingService {

    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
        sendNotification(remoteMessage);
    }
    // [END receive_message]

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param remoteMessage FCM RemoteMessage received.
     */
    private void sendNotification(RemoteMessage remoteMessage) {

        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

// this is a my insertion looking for a solution
        int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.myicon: R.mipmap.myicon;
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(icon)
                .setContentTitle(remoteMessage.getFrom())
                .setContentText(remoteMessage.getNotification().getBody())
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }

}

【问题讨论】:

  • firebase 与您创建通知的方式无关,请提供您所看到内容的图片
  • 准确。此代码直接来自 Firebase,并且 sendNotification() 方法对于任何通知都完全相同。此代码适用于 GCM,但适用于 FCM 编号。它始终保持 ic_launcher,使用新的 Web 界面发送消息
  • 你设置的是小图标而不是大图标,除非你在推送有效载荷中发送带有通知标签的推送,它与 FCM 无关
  • 当应用程序在前台时是否显示您的自定义通知图标?这对我行得通。但是,当应用程序在后台时,它必须使用某种默认的 FCM 处理程序,因为所有通知设置都会被忽略(图标、声音、灯光、振动等无法自定义)。

标签: android push-notification firebase googleio firebase-cloud-messaging


【解决方案1】:

我想我会为此添加一个答案,因为我的问题很简单但很难注意到。特别是我在创建com.google.firebase.messaging.default_notification_icon 时复制/粘贴了一个现有的元数据元素,它使用android:value 标记来指定其值。这不适用于通知图标,一旦我将其更改为android:resource,一切都按预期工作。

【讨论】:

  • default_notification_color 元数据也是如此,它必须是 android:resource - 设置为 android:value 将不起作用
【解决方案2】:

写这个

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

右下角&lt;application.....&gt;

【讨论】:

  • 对我不起作用
【解决方案3】:

如果您的应用在后台,通知图标将设置为 onMessage Receive 方法,但如果您的应用在前台,通知图标将是您在清单中定义的图标

【讨论】:

    【解决方案4】:

    atm 他们正在处理这个问题https://github.com/firebase/quickstart-android/issues/4

    当您从 Firebase 控制台发送通知时,默认使用您的应用图标,Android 系统会在通知栏中将该图标变为纯白色。

    如果您对该结果不满意,您应该实施 FirebaseMessagingService 并在收到消息时手动创建通知。我们正在努力改进这一点,但目前这是唯一的方法。

    编辑:使用 SDK 9.8.0 添加到 AndroidManifest.xml

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

    【讨论】:

    • 如何在棉花糖中显示自定义图标通知托盘
    【解决方案5】:

    很遗憾,这是 SDK 9.0.0-9.6.1 中 Firebase 通知的限制。当应用程序在后台时,启动器图标会从清单(带有必要的 Android 着色)中用于从控制台发送的消息。

    但是,使用 SDK 9.8.0,您可以覆盖默认值!在您的 AndroidManifest.xml 中,您可以设置以下字段来自定义图标和颜色:

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

    请注意,如果应用程序在前台(或发送数据消息),您完全可以使用自己的逻辑来自定义显示。如果从 HTTP/XMPP API 发送消息,您还可以始终自定义图标。

    【讨论】:

    • @Ian Barber:Google 有什么计划在不久的将来改变这种行为吗?
    • 团队已意识到该问题并正在努力修复。
    • 这有什么更新吗?我想我会问,因为在某些情况下,Google 工程师只是忘记推送补丁。
    • 啊,我让它与 9.8.0 一起工作。为了帮助他人,请记住您的状态栏图标必须符合要求:developer.android.com/guide/practices/ui_guidelines/…。我的没有,因此 firebase 只是默认为标准 whitesquare,而不是使用清单中指定的图标。
    • 如果您碰巧尝试此操作并发现图标小于其他通知,请确保您使用的是矢量绘图(而不是 png)。这为我解决了。
    【解决方案6】:

    我的解决方案类似于 ATom 的解决方案,但更易于实施。您不需要创建一个完全隐藏 FirebaseMessagingService 的类,您只需覆盖接收 Intent 的方法(至少在版本 9.6.1 中是公共的)并从附加组件中获取要显示的信息。 “hacky”部分是方法名称确实被混淆了,并且每次您将 Firebase sdk 更新到新版本时都会更改,但是您可以通过使用 Android Studio 检查 FirebaseMessagingService 并寻找一个公共方法来快速查找它一个 Intent 作为唯一的参数。在 9.6.1 版本中,它被称为 zzm。 这是我的服务的样子:

    public class MyNotificationService extends FirebaseMessagingService {
    
        public void onMessageReceived(RemoteMessage remoteMessage) {
            // do nothing
        }
    
        @Override
        public void zzm(Intent intent) {
            Intent launchIntent = new Intent(this, SplashScreenActivity.class);
            launchIntent.setAction(Intent.ACTION_MAIN);
            launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* R    equest code */, launchIntent,
                    PendingIntent.FLAG_ONE_SHOT);
            Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(),
                    R.mipmap.ic_launcher);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_notification)
                    .setLargeIcon(rawBitmap)
                    .setContentTitle(intent.getStringExtra("gcm.notification.title"))
                    .setContentText(intent.getStringExtra("gcm.notification.body"))
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent);
    
            NotificationManager notificationManager =
                    (NotificationManager)     getSystemService(Context.NOTIFICATION_SERVICE);
    
            notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
        }
    }
    

    【讨论】:

    • gcm.notification.title for key name 对于所有版本都是 100% 安全的?
    【解决方案7】:

    还有一种丑陋但有效的方法。反编译 FirebaseMessagingService.class 并修改它的行为。然后只需将类放在 yout app 中的正确包中,然后 dex 使用它而不是消息传递库本身中的类。它非常简单且有效。

    有方法:

    private void zzo(Intent intent) {
        Bundle bundle = intent.getExtras();
        bundle.remove("android.support.content.wakelockid");
        if (zza.zzac(bundle)) {  // true if msg is notification sent from FirebaseConsole
            if (!zza.zzdc((Context)this)) { // true if app is on foreground
                zza.zzer((Context)this).zzas(bundle); // create notification
                return;
            }
            // parse notification data to allow use it in onMessageReceived whe app is on foreground
            if (FirebaseMessagingService.zzav(bundle)) {
                zzb.zzo((Context)this, intent);
            }
        }
        this.onMessageReceived(new RemoteMessage(bundle));
    }
    

    此代码来自 9.4.0 版本,由于混淆,方法在不同版本中会有不同的名称。

    【讨论】:

      【解决方案8】:

      只需将 targetSdkVersion 设置为 19。通知图标将被着色。 然后等待 Firebase 解决此问题。

      【讨论】:

      • :D 哇,副作用列表在哪里?
      • @EugenPechanec 是的,权衡是您可能无法使用 20+ 上可用的某些 API
      【解决方案9】:

      使用服务器实现向您的客户端发送消息并使用 数据 类型的消息而不是 通知消息类型。

      这将帮助您获得对onMessageReceived 的回调,无论您的应用是在后台还是前台,然后您都可以生成自定义通知

      【讨论】:

      • 这也是 Firebase 文档中建议的解决方案,如果您依赖数据推送而不是通知,则可以以任何您喜欢的方式显示通知。
      • 是的,同意。这应该被标记为正确答案。或者我在下面的答案:)
      • 不,对于需要与其他需要通知的客户端/旧版本保持兼容性的人来说,这是不可行的。
      • 我们在生产中的应用程序已经期望推送通知类型,我们已经扩展了(复杂的)后端组件来为新客户端添加数据。但我们无法取消对旧版应用的支持。
      • 我指出您的“解决方案”需要更改后端,有时这不是一个选项。
      【解决方案10】:

      我正在从 FCM 控制台和通过 HTTP/JSON 触发我的通知......结果相同。

      我可以处理标题、完整消息,但图标始终是默认的白色圆圈:

      Notification screenshot

      代替我在代码中的自定义图标(setSmallIcon 或 setSmallIcon)或应用中的默认图标:

       Intent intent = new Intent(this, MainActivity.class);
          // use System.currentTimeMillis() to have a unique ID for the pending intent
          PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
      
          if (Build.VERSION.SDK_INT < 16) {
              Notification n  = new Notification.Builder(this)
                      .setContentTitle(messageTitle)
                      .setContentText(messageBody)
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentIntent(pIntent)
                      .setAutoCancel(true).getNotification();
              NotificationManager notificationManager =
                      (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
              //notificationManager.notify(0, n);
              notificationManager.notify(id, n);
          } else {
              Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
      
              Notification n  = new Notification.Builder(this)
                      .setContentTitle(messageTitle)
                      .setContentText(messageBody)
                      .setSmallIcon(R.drawable.ic_stat_ic_notification)
                      .setLargeIcon(bm)
                      .setContentIntent(pIntent)
                      .setAutoCancel(true).build();
      
              NotificationManager notificationManager =
                      (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
              //notificationManager.notify(0, n);
              notificationManager.notify(id, n);
          }
      

      【讨论】:

      • 知道了!我的 标签超出了 AndroidManifest.xml 中的 标签这里我回答了stackoverflow.com/a/37352142/6366150
      • 仅适用于前台应用程序运行...在后台仍然获得相同的行为
      • 当应用程序在前台客户通知图标即将到来并且工作正常,但在应用程序后台得到白色方形图标请帮助我
      猜你喜欢
      • 2017-09-04
      • 2019-06-19
      • 2021-12-19
      • 2016-12-25
      • 2017-11-18
      • 1970-01-01
      • 2017-02-06
      相关资源
      最近更新 更多