如何在应用程序未运行时堆叠Firebase Cloud Messaging通知?

The*_*ook 3 android firebase firebase-cloud-messaging

Firebase Cloud Messaging用来从我的服务器发送推送通知到我的Android应用程序.

当应用程序运行时,通知会堆叠,因为我将它们设置为我的组中的组FirebaseMessagingService.这很好.

但是,当应用程序未运行时,通知不会堆叠,并且每个通知都会单独显示.这不好.

即使应用程序未运行,如何确保通知堆叠?

这是我的FirebaseMessagingService样子:

public class MyFcmListenerService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        RemoteMessage.Notification notification = remoteMessage.getNotification();

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)

                .setSmallIcon(R.drawable.notif_white)
                .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.notif_white))
                .setContentTitle(getResources().getString(R.string.app_name))
                .setContentText(notification.getBody())
                .setAutoCancel(true)
                .setPriority(2)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent)
                .setGroup("1")
                .setGroupSummary(true)
                .setOnlyAlertOnce(true);


        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 , notificationBuilder.build());

        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 5

要堆叠两个或多个通知(在消息列表中指定)并使它们显示为GMail样式通知,您可以为通知添加收件箱样式,如下所示: -

    private void showNotification(Context mContext, String title, List messages, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {

    final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
            mContext);

    NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

    for(int i=0;i<messages.size();i++)
        inboxStyle.addLine(messages.get(i));

    Notification notification;
    notification = mBuilder.setTicker(title)
            .setAutoCancel(true)
            .setContentTitle(title)
            .setContentIntent(resultPendingIntent)
            .setSound(alarmSound)
            .setStyle(inboxStyle)
            .setWhen(getTimeMilliSec(timeStamp))
            .setSmallIcon(R.drawable.notification_small_icon)
            .setLargeIcon(R.drawable.notification_large_icon)
            .setDeleteIntent(PendingIntent.getBroadcast(mContext,101,new Intent(mContext, NotificationDismissedReceiver.class),PendingIntent.FLAG_CANCEL_CURRENT))
            .build();

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(NConfig.NOTIFICATION_ID, notification);
    }
Run Code Online (Sandbox Code Playgroud)

如果您注意到,我还为我的通知添加了删除意图,该意图触发NotificationDismissedReceiver(BroadcastReceiver),其主要工作是清除通过滑动手势解除的通知消息,以便下次只有新通知消息堆叠在一起.

public class NotificationDismissedReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // TODO: This method is called when the BroadcastReceiver is receiving
    // an Intent broadcast.
    messages.clear();
}
}
Run Code Online (Sandbox Code Playgroud)

主要逻辑是收集列表中的所有未读/未擦除通知,即消息,下面是FirebaseMessagingService的onMessageReceive(): -

    public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.e(TAG, "From: " + remoteMessage.getFrom());

    if (remoteMessage == null)
        return;

    if (remoteMessage.getData()!=null && remoteMessage.getData().size() > 0) 
    {

        try {
            JSONObject json = new JSONObject(remoteMessage.getData().toString());
            Log.e(TAG, "Notification Data: " + json);
            Title = json.get("title").toString();
            Message = json.get("body").toString();
            messages.add(Message);

        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
     }

       showNotification(...);
     }
Run Code Online (Sandbox Code Playgroud)

当应用程序在前台时,FirebaseMessagingService的上述onMessageReceive()执行正常,但是当您的应用程序处于后台或被杀死时,它不会执行.要使其执行,您必须从服务器端发送的JSON消息中省略通知部分,并且仅包括数据部分,如下所示: -

       var data = new
       {
           to = token,
        //   notification = new
        //   {
        //       body = messageBody,   //Omitting notification part of data
        //       title = messageTitle,
        //       icon = "myicon",
        //},
        data = new
        {
               body = messageBody,  // adding all notification information inside data
               title = messageTitle,
               icon = "myicon",
           }
       };
Run Code Online (Sandbox Code Playgroud)

通过这样做,您的消息现在变为仅数据消息,这意味着它将始终执行FirebaseMessagingService的onMessageReceive(),无论您的应用程序是在后台还是前台.

希望这么多解释有所帮助.


Mad*_*ddy 5

onMessageReceived当您的应用在后台或被杀时,Firebase不会呼叫您,并且您无法自定义您的通知.系统生成的通知将显示.

使Firebase库onMessageReceived在每种情况下都能调用你的名字

a)前景

b)背景

c)被杀

您不能在请求中将JSON密钥"通知"放入firebase API,而是使用"数据",请参阅下文.

例如,以下消息将不会调用 onMessageReceived()

{
  "to": "/topics/test",
  "notification": {
    "title" : "title",
    "message": "data!"
   }
}
Run Code Online (Sandbox Code Playgroud)

但这会奏效

{
  "to": "/topics/test",
   "data": {
       "title":"title",
       "message":"data!"
   }
} 
Run Code Online (Sandbox Code Playgroud)

看到它具有火力消息类型例如的详细描述:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        sendNotification(remoteMessage.getData().get("message").toString(), remoteMessage.getData().get("title").toString());
    }

}

private void sendNotification(String message, String title) {
        int requestID = (int) System.currentTimeMillis();
        Intent intent = new Intent(this, activityCompat);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.small_logo)
                .setContentTitle(title)
                .setContentText(message).setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(messageBody))
                .setTicker(messageBody);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
        Notification notification = notificationBuilder.build();

        notificationManager.notify(0, notification);

}
Run Code Online (Sandbox Code Playgroud)