我正在使用Firebase并测试在应用程序处于后台时从我的服务器向我的应用发送通知 . 通知成功发送,甚至出现在设备的通知中心,但是当通知出现或甚至我点击它时,我的FCMessagingService内的onMessageReceived方法永远不会被调用 .
当我的应用程序在前台测试时,onMessageReceived方法被调用,一切正常 . 当应用程序在后台运行时,会出现此问题 .
这是预期的行为,还是有办法解决这个问题?
这是我的FBMessagingService:
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class FBMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.i("PVL", "MESSAGE RECEIVED!!");
if (remoteMessage.getNotification().getBody() != null) {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
} else {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
}
}
}
23 回答
只需覆盖FirebaseMessagingService的OnCreate方法即可 . 当您的应用处于后台时调用它:
有两种类型的消息:通知消息和数据消息 . 如果您只发送数据消息,那就没有了消息字符串中的通知对象 . 它将在您的应用程序在后台调用 .
这是按预期工作的,只有当您的应用位于前台时,通知消息才会传递到您的onMessageReceived回调 . 如果您的应用在后台或已关闭,则会在通知中心显示通知消息,以及由于用户点击通知而启动的任何 data from that message is passed to the intent .
您可以指定click_action以指示在用户点击通知时应启动的意图 . 如果未指定click_action,则使用主活动 .
当意图启动时,您可以使用
检索包含与通知消息一起发送的任何数据的Set .
有关通知消息的更多信息,请参阅docs .
Remove notification field 完全来自您的服务器请求 . 发送 only data 并在
onMessageReceived()
处理它,否则当应用程序处于后台或被杀时,您的onMessageReceived()
将不会被触发 .不要忘记在通知请求中包含
"priority": "high"
字段 . 根据文档:数据消息以正常优先级发送,因此它们不会立即到达;这也可能是问题所在 .这是我从服务器发送的内容
所以你可以像这样在
onMessageReceived(RemoteMessage message)
收到你的数据....让我说我必须得到身份证明DEPRECATED SOLUTION:
我有一个完美的解决方案:
您需要执行两个简单的步骤:
将您的firebase升级到版本编译
com.google.firebase:firebase-messaging:10.2.1
覆盖
FirebaseMessagingService
类中的handleIntent(Intent intent)
方法 .无论app处于前景,后台还是被杀死状态,每次都会调用
handleIntent()
方法 .我有同样的问题 . 使用“数据消息”而不是“通知”更容易 . 数据消息始终加载类onMessageReceived .
在该课程中,您可以使用notificationbuilder自行发出通知 .
例:
这里有关于firebase消息的更清晰的概念 . 我是从他们的支持团队那里找到的 .
Firebase has three message types :
Notification messages :通知消息适用于背景或前景 . 当应用程序处于后台时,通知消息将传递到系统托盘 . 如果应用程序位于前台,则消息由
onMessageReceived()
或didReceiveRemoteNotification
回调处理 . 这些基本上就是所谓的显示消息 .Data messages :在Android平台上,数据信息可以在后台和前台工作 . 数据消息将由onMessageReceived()处理 . 这里的平台特定说明如下:在Android上,可以在用于启动活动的Intent中检索数据有效负载 . 详细说明,如果你有
"click_action":"launch_Activity_1"
,你可以通过getIntent()
仅从Activity_1
检索此意图 .Messages with both notification and data payloads :在后台,应用程序在通知托盘中接收通知有效负载,并仅在用户点击通知时处理数据有效负载 . 在前台时,您的应用会收到一个消息对象,其中包含两个可用的有效负载 . 其次,click_action参数通常用于通知有效负载而不是数据有效负载 . 如果在数据有效内容中使用,则此参数将被视为自定义键值对,因此您需要实现自定义逻辑以使其按预期工作 .
另外,我建议您使用onMessageReceived方法(请参阅数据消息)来提取数据包 . 根据您的逻辑,我检查了bundle对象,但没有找到预期的数据内容 . 以下是对类似案例的引用,可能会提供更清晰的说明 .
欲了解更多信息,请访问我的this thread
收到消息且您的应用程序处于后台时,通知将发送到主要活动的额外意图 .
您可以检查主活动的oncreate()或onresume()函数中的额外值 .
您可以检查数据,表格等字段(通知中指定的字段)
例如,我使用数据作为密钥发送
根据Firebase Cloud Messaging文档 - 如果Activity在前台,则将调用onMessageReceived . 如果“活动”处于后台或已关闭,则通知中心会显示应用启动器活动的通知消息 . 如果您的应用处于后台,可以通过调用用于firebase消息传递的rest service api来点击通知来调用您的自定义活动:
URL- https://fcm.googleapis.com/fcm/send
方法类型 - POST
车身/有效载荷:
在您的应用中,您可以在要调用的活动中添加以下代码:
如果app处于后台模式或处于非活动状态(已终止),并且 click 在 Notification 上,则应检查LaunchScreen中的有效负载(在我的情况下,启动屏幕为MainActivity.java) .
所以在 MainActivity.java 上 onCreate 检查 Extras :
我遇到了同样的问题 . 如果应用程序是前台 - 它会触发我的后台服务,我可以根据通知类型更新我的数据库 . 但是,应用程序进入后台 - 默认通知服务将注意向用户显示通知 .
这是我在后台识别应用程序并触发后台服务的解决方案,
在manifest.xml中
在最新的Android 8.0版本中测试了这个解决方案 . 谢谢
覆盖
FirebaseMessageService
的handleIntent
方法适用于我 .这里的代码在 C# (Xamarin)
这就是 Java 中的守则
默认情况下,当您的应用程序处于后台并且您单击通知时,您应用程序中的Launcher Activity将被启动,如果您有任何数据部分与您的通知,您可以在以下相同的活动中处理它,
即使应用程序已关闭,背景也在前台,我已经实现了这种简单的方式来发送消息 . 我之前使用的是
firebase
控制台,但我只收到消息,而不是图像和自定义数据 .要使用图像发送此自定义数据,您可以使用名为
AdvancedREST Client
的工具,它是Chrome扩展程序,并使用以下参数发送消息:使用这个
url:- https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=Your Server key From or Authorization key
(见下面参考)可以通过访问Google开发人员控制台并单击项目左侧菜单上的“凭据”按钮来获取授权密钥 . 在列出的API密钥中,服务器密钥将是您的授权密钥 .
并且您需要将
tokenID
接收器放在使用API发送的POST
请求的to
部分中 .这段android代码//消息将包含Push消息
如果应用程序在后台默认处理通知Fire-base但是如果我们想要自定义通知而不是我们必须更改我们的服务器端,负责发送我们的自定义数据(数据有效负载)
完全从服务器请求中删除通知有效内容 . 仅发送数据并在onMessageReceived()中处理它,否则当应用程序处于后台或被杀死时,不会触发onMessageReceived .
现在,您的服务器端代码格式如下,
NOTE :在上面的代码中看到这一行
"text":"John Doe shared a contact in the group Contact Exchange"在数据有效负载中,您应使用"text"参数而不是"body"或"message"参数进行消息描述或任何您想要使用的文本 .
onMessageReceived()
只需在MainActivity的onCreate方法中调用它:
根据t3h Exi的解决方案,我想在这里发布干净的代码 . 只需将其放入MyFirebaseMessagingService,如果应用程序处于后台模式,一切正常 . 您至少需要编译com.google.firebase:firebase-messaging:10.2.1
试试这个:
我遇到了这个问题(如果应用程序处于后台或已关闭,应用程序不希望在通知单击时打开),并且问题在通知正文中无效
click_action
,请尝试删除或将其更改为有效的内容 .我遇到了同样的问题,并对此进行了更多的挖掘 . 当应用程序在后台时, notification message 被发送到系统托盘,但是 data message 被发送到
onMessageReceived()
见https://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
和https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java
为了确保您发送的消息,文档说“使用您的应用服务器和FCM服务器API:仅设置数据密钥 . 可以是可折叠的,也可以是不可折叠的 . ”
见https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
值得强调的一点是,即使应用程序处于后台,您也必须使用数据消息-- data key only 来获取onMessageReceived处理程序 . 如果应用程序处于后台,您不应该被触发 .
这里提到了(但在FCM文档中没有这么强调):
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
我正在使用的后端是使用 Notification messages 而不是数据消息 . 因此,在阅读完所有答案之后,我试图从发起活动的意图包中检索额外内容 . 但无论我试图从
getIntent().getExtras();
检索哪些键,该值始终为null .但是,我终于找到了一种使用 Notification messages 发送数据的方法,并从意图中检索它 .
这里的关键是将 data payload 添加到Notification消息中 .
例:
执行此操作后,您将能够以这种方式获取您的信息:
intent.getExtras().getString("title")
将message_title
和
intent.getExtras().getString("message")
将是message_body
Reference
如果您的问题与显示大图像有关,即您是否使用来自firebase控制台的图像发送推送通知,并且仅当应用程序位于前台时才显示图像 . 此问题的解决方案是发送仅包含数据字段的推送消息 . 像这样的东西: