当应用程序处于前台或后台时如何使用FCM处理通知 [英] How to handle notifications with FCM when app is in either foreground or background

查看:165
本文介绍了当应用程序处于前台或后台时如何使用FCM处理通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用firebase构建我的项目.
它还将使用FCM(firebase云消息).
但是有一个问题.
当应用程序在后台运行时,我无法处理FCM(创建我的自定义通知).

官方网站教程说,
情况1:应用程序前台->覆盖"onMessageReceived()"以创建自定义通知.
情况2:应用程序后台->系统将直接创建通知.我们不需要也不能做任何事情.因为在这种情况下它不会触发"onMessageReceived()".

I used firebase to build My project.
It will also use the FCM (firebase cloud message).
But there is a problem.
I can't handle the FCM (create my custom notificaion) when app is in background.

The official site tutorial said that
case 1: App foreground -> override the "onMessageReceived()" to create your custom notification.
case 2: App background -> System will create the notification directly. We needn't and can't do anything. Because it doesn't trigger the "onMessageReceived()" in this case.

但是,如果应用程序在后台运行时我什么也不做,则无法创建自定义通知. (例如,在用户单击通知后,它将弹出一个窗口以显示详细信息.)

However if I can do nothing when app is background, I can't create my custom notification. (e.g. After Users click the notification and it will pop up a window to show detail information.)

那么当应用程序在后台运行时,如何使用FCM处理通知?

So how do I handle notifications with FCM when app is in background?

推荐答案

有一个坏消息.
Google在版本'com.google.firebase:firebase-messaging:11.6中更改了Firebase源代码. 0'.
handelIntent现在是公共最终无效方法".这意味着我们无法覆盖它.
如果要使用该解决方案,请将版本更改为"com.google.firebase:firebase-messaging:11.4.2"

There is a bad news.
Google change the Firebase source code in version 'com.google.firebase:firebase-messaging:11.6.0'.
handelIntent is "public final void method" now. which means we can't override it .
If you want to use the solution, change the version to be "com.google.firebase:firebase-messaging:11.4.2"



尽我所能.它可以在高于Android 6.0以上版本(API级别23)的项目构建版本上正常运行,并且我已经尝试过了.



Try my way. It can perfectly work on the project build version is Android 6.0 above(api level 23) and I have tried it already.

官方网站教程

官方网站表示,当应用程序处于后台时,通知将由系统创建.因此,您无法通过覆盖"onMessageReceived()"来处理它.因为仅在应用程序处于前台时才触发"onMessageReceived()".

The official site said that the notification will be created by system when app is in background. So you can't handle it by overriding the "onMessageReceived()". Because the "onMessageReceived()" is only triggered when app is in foreground.

但事实并非如此.实际上,通知(当应用程序处于后台时)是由Firebase库创建的.

But the truth is not. Actually the notificaions (when app is in background) are created by Firebase Library.

我跟踪了Firebase库代码.我找到了更好的方法.

After I traced the firebase library code. I find a better way.

步骤1.在FirebaseMessagingService中覆盖"handleIntent()"而不是"onMessageReceived()"
为什么:
由于该方法将被触发,因此应用程序将处于前台或后台.因此,在两种情况下,我们都可以处理FCM消息并创建我们的自定义通知.

Step 1. Override the "handleIntent()" instead of "onMessageReceived()" in FirebaseMessagingService
why:
Because the method will be trigger either app is in foreground or the background. So we can handle FCM message and create our custom notifications in both cases.

@Override
public void handleIntent(Intent intent) {
    Log.d( "FCM", "handleIntent ");
}


步骤2.解析来自FCM的消息
方式:
如果您不知道所设置消息的格式.打印并尝试解析.
这是基本图示

Step 2. Parse the message from FCM
how:
If you don't know the format of the message you set. Print it and try to parse it.
Here is the basic illustration

Bundle bundle = intent.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        Object value = bundle.get(key);
        Log.d("FCM", "Key: " + key + " Value: " + value);
    }
}


第2步.在应用程序处于后台状态时,删除Firebase库创建的通知
为什么:
我们可以创建自定义通知.但是Firebase Library创建的通知仍然存在(实际上它是由"super.handleIntent(intent)"创建的.下面有详细说明.).然后,我们将有两个通知.那真是太奇怪了.因此,我们必须删除Firebase库创建的通知.

方式(项目构建级别为Android 6.0以上):
识别要删除的通知并获取信息.并使用"notificationManager.cancel()"将其删除.

Step 2. Remove the notifications created by Firebase library when the app is in background
why:
We can create our custom notification. But the notification created by Firebase Library will still be there (Actually it created by ""super.handleIntent(intent)"". There is detail explaination below.). Then we'll have two notifcations. That is rather weird. So we have to remove the notificaion created by Firebase Library

how (project build level is Android 6.0 above):
Recognize the notifications which we want to remove and get the informaion. And use the "notificationManager.cancel()" to remove them.

private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
    }


    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "StatusBarNotification tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}

我的整个示例代码:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static int notificationCount=0;

@Override
public void handleIntent(Intent intent) {
    //add a log, and you'll see the method will be triggered all the time (both foreground and background).
    Log.d( "FCM", "handleIntent");

    //if you don't know the format of your FCM message,
    //just print it out, and you'll know how to parse it
    Bundle bundle = intent.getExtras();
    if (bundle != null) {
        for (String key : bundle.keySet()) {
            Object value = bundle.get(key);
            Log.d("FCM", "Key: " + key + " Value: " + value);
        }
    }

    //the background notification is created by super method
    //but you can't remove the super method. 
    //the super method do other things, not just creating the notification
    super.handleIntent(intent);

    //remove the Notificaitons
    removeFirebaseOrigianlNotificaitons();

    if (bundle ==null)
        return;

    //pares the message
    CloudMsg cloudMsg = parseCloudMsg(bundle);

    //if you want take the data to Activity, set it
    Bundle myBundle = new Bundle();
    myBundle.putSerializable(TYPE_FCM_PLATFORM, cloudMsg);
    Intent myIntent = new Intent(this, NotificationActivity.class);
    myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    myIntent.putExtras(myBundle);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationCount, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    //set the Notification
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.icon)
            .setContentTitle(cloudMsg.getTitle())
            .setContentText(cloudMsg.getMessage())
            .setAutoCancel(true)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(notificationCount++, notificationBuilder.build());
}



/**
 * parse the message which is from FCM
 * @param bundle
 */
private CloudMsg parseCloudMsg(Bundle bundle) {
    String title = null, msg=null;

    //if the message is sent from Firebase platform, the key will be that
    msg = (String) bundle.get("gcm.notification.body");

    if(bundle.containsKey("gcm.notification.title"))
    title = (String) bundle.get("gcm.notification.title");

    //parse your custom message
    String testValue=null;
    testValue =  (String) bundle.get("testKey");

    //package them into a object(CloudMsg is your own structure), it is easy to send to Activity.
    CloudMsg cloudMsg = new CloudMsg(title, msg, testValue);
    return cloudMsg;
}


/**
 * remove the notification created by "super.handleIntent(intent)"
 */
    private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
     }

    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}
}

这篇关于当应用程序处于前台或后台时如何使用FCM处理通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆