gpt4 book ai didi

android - 当应用程序处于前台或后台时如何使用 FCM 处理通知

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:07:33 26 4
gpt4 key购买 nike

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

The official site tutorial
情况 1:应用程序前台 -> 覆盖“onMessageReceived()”以创建您的自定义通知。
案例二:App后台->系统会直接创建通知。我们不需要也不能做任何事情。因为在这种情况下它不会触发“onMessageReceived()”。

但是,如果当应用程序处于后台时我什么也做不了,我就无法创建自定义通知。 (例如,用户点击通知后,会弹出一个窗口显示详细信息。)

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

最佳答案

有个坏消息。
谷歌更改版本“com.google.firebase:firebase-messaging:11.6.0”中的 Firebase 源代码。
handelIntent 现在是“公共(public)最终无效方法”。这意味着我们无法覆盖它。
如果要使用该解决方案,请将版本更改为“com.google.firebase:firebase-messaging:11.4.2”



试试我的方法。项目构建版本为Android 6.0以上(api level 23)可以完美运行,我已经尝试过了。

有比 official site tutorial 更好的方法

官网说是app在后台的时候系统会发出通知。所以你不能通过覆盖“onMessageReceived()”来处理它。因为“onMessageReceived()”仅在应用程序处于前台时触发。

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

在我追踪到 firebase 库代码之后。我找到了更好的方法。

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 ");
}


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);
}
}


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);
}
}

The my whole sample code:

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);
}
}
}

关于android - 当应用程序处于前台或后台时如何使用 FCM 处理通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48897883/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com