Android firebase消息推送集成 FCM消息处理

2024-05-27 01:28

本文主要是介绍Android firebase消息推送集成 FCM消息处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FirebaseMessagingService 是 Firebase Cloud Messaging (FCM) 提供的一个服务,用于处理来自 Firebase 服务器的消息。它有几个关键的方法,你提到的 onMessageReceiveddoRemoteMessagehandleIntent 各有不同的用途。下面逐一解释这些方法的作用和用法:

1. onMessageReceived(RemoteMessage message)

当你的应用处于前台时,如果有消息到达,就会回调 onMessageReceived 方法。这里是处理接收到的消息的逻辑部分。

override fun onMessageReceived(message: RemoteMessage) {super.onMessageReceived(message)// 你可以根据消息(message)的内容来做相应的处理,// 比如展示通知,更新UI等。
}

2. doRemoteMessage()

FirebaseMessagingService 的官方文档中,并没有直接提及 doRemoteMessage 这个方法。它可能是某个特定项目或库中特有的方法,而不是 Firebase SDK 的一部分。如果它存在于你的代码或你使用的某个库中,可能需要查找特定的文档或源代码来了解其具体用途。

3. handleIntent(Intent intent)

handleIntent 方法在服务中处理意图(Intent)。它不是 FirebaseMessagingService 专有的方法,而是 Android Service 类的一部分,可能会在接收到 Intent 时被调用。然而,在处理 FCM 相关的任务中,你通常不需要直接覆写或调用 handleIntent 方法。FCM 服务通常会自动处理消息的接收和分发工作,包括将消息派发到 onMessageReceived 方法。

如果你需要在后台接收消息并触发一些行为,通常会使用 onMessageReceived 来实现逻辑,因为 FCM 为这种用例提供了足够的支持。

注意:如果你的应用在后台,Firebase 通常会自动处理消息。如果消息中包含了通知负载,系统可能会自动显示通知,而不会调用 onMessageReceived。如果想要确保后台消息也触发 onMessageReceived,需要在发送消息时仅使用数据负载(即不包含通知负载),并确保应用实现了适当的后台运行条件(例如,使用高版本的 targetSdkVersion,考虑到 Android 的后台执行限制等)。

总之,对于绝大多数使用 Firebase Cloud Messaging 的场景,你主要会与 onMessageReceived 方法打交道,对于特殊的或自定义的方法(如 doRemoteMessage),需要参考特定的文档或代码实现。

当你使用 Firebase Cloud Messaging (FCM) 发送消息时,消息可以包含两种类型的数据:

  1. 通知负载:当应用在前台运行时,通过 onMessageReceived 处理;当应用在后台或被杀死时,系统会自动处理。
  2. 数据负载:无论应用是在前台、后台还是被杀死,都会触发 onMessageReceived(需要特定格式的负载才会在后台触发)。

以下是如何在 FirebaseMessagingServiceonMessageReceived 方法中获取消息标题、消息体和任意附加的数据(如 deeplink)的一个示例:

完整的 FirebaseMessagingService 示例

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessageclass MyFirebaseMessagingService : FirebaseMessagingService() {override fun onMessageReceived(remoteMessage: RemoteMessage) {super.onMessageReceived(remoteMessage)// 获取消息标题和内容(消息负载)val title = remoteMessage.notification?.title ?: "Default Title"val messageBody = remoteMessage.notification?.body ?: "Default Message Body"// 获取数据(数据负载)val data = remoteMessage.dataval deeplink = data["deeplink"] // 假定有一个键为"deeplink"的数据// 展示通知sendNotification(title, messageBody, deeplink ?: "default_deeplink")}private fun sendNotification(title: String, messageBody: String, deeplink: String) {val channelId = "YOUR_CHANNEL_ID"createNotificationChannel()val builder = NotificationCompat.Builder(this, channelId).setSmallIcon(R.drawable.ic_launcher_foreground) // 更改为你的通知图标.setContentTitle(title).setContentText(messageBody).setPriority(NotificationCompat.PRIORITY_DEFAULT)with(NotificationManagerCompat.from(this)) {// notificationId 是定义通知的唯一 int 值notify(System.currentTimeMillis().toInt(), builder.build())}// 处理 deeplink 或是其他额外的逻辑...}// Android 8.0 及以上需要创建通知频道private fun createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val name = "Channel Name"val descriptionText = "Channel Description"val importance = NotificationManager.IMPORTANCE_DEFAULTval channel = NotificationChannel("YOUR_CHANNEL_ID", name, importance).apply {description = descriptionText}val notificationManager: NotificationManager =getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagernotificationManager.createNotificationChannel(channel)}}
}

请注意,您需要修改 R.drawable.ic_launcher_foreground 到您实际的通知图标资源,同时 "YOUR_CHANNEL_ID" 应该替换为您应用中的实际通知频道 ID。

通过上述代码,当 FCM 消息到达时(无论应用在前台、后台还是被杀死),onMessageReceived 都将触发(前提是符合数据消息的接收条件),您可以获取消息中的标题、消息体和附加的数据(如 deeplink),然后根据这些信息展示一条自定义通知。

在使用 Firebase Cloud Messaging (FCM) 时,您的应用可以接收两种类型的消息:通知消息数据消息。处理这些消息的方式与应用的前台/后台状态有关,以及消息的类型。

onMessageReceived 方法

onMessageReceived 方法在以下情况下被调用:

  • 应用在前台时,不论消息类型。
  • 应用在后台或被杀死时,仅当消息是数据消息(或通知和数据的混合消息,在这种情况下,数据部分被送达)。

处理后台消息

当您的应用处于后台或被杀死状态时,如果是纯通知消息,FCM 会自动展示通知,无需编写额外的接收代码。此外,点击通知可以自动打开应用或启动指定的活动(Activity),您可以在消息中指定 click_action 字段来指定要启动的活动,并在该活动中处理深链接。

实现深链接的点击响应

为了在点击通知后执行消息中携带的深链接,您可以:

  1. 在发送的消息中,设定通知消息的 click_action 属性,并为其指定一个唯一的值。
  2. 在应用的 AndroidManifest.xml 中,给相应的活动(Activity)配置一个 Intent Filter,该 Intent Filter 捕捉上一步中定义的 click_action

例如,您的消息结构可能如下所示:

{"to" : "FCM_TOKEN","notification" : {"body" : "消息正文","title": "消息标题","click_action":"OPEN_ACTIVITY_1"},"data" : {"extra_info" : "some_extra_information","deep_link" : "yourapp://deeplink/path"}
}

然后,在 AndroidManifest.xml 中配置捕捉这个动作的活动:

<activityandroid:name=".YourActivity"><intent-filter><action android:name="OPEN_ACTIVITY_1" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</activity>

YourActivity 中,您可以获取数据并处理深链接:

if (intent.extras != null) {val deepLink = intent.extras.getString("deep_link")// 根据 deepLink 进行导航或其他操作
}

注意

当您的应用在后台或被杀死时接收通知消息,并且您希望在用户点击通知时执行一些代码(如处理深链接)时,上述方法一般可以实现目的。但是,如果需要在应用在后台或被杀死时收到的数据消息也能展示通知,并在点击时执行相应深链接,您需要在 onMessageReceived 方法中手动构建并展示通知,并处理点击事件。这一点非常重要,因为在后台时,数据消息不会自动展示通知,必须手动实现。

综上,您不需要(也不应该)直接修改 handleIntent 方法来处理普通的 FCM 消息。相反,您应专注于根据消息的类型和应用的状态,合理地使用 onMessageReceived 并处理通知的创建与点击响应。

在 Android 中,如果你想在收到 Firebase Cloud Messaging (FCM) 消息后展示自定义样式的通知,你可以在 onMessageReceived 方法中创建并展示一个通知。这给了你完全的控制权,允许你自定义通知的外观和行为。

以下是创建并展示一个自定义样式通知的基本步骤:

步骤 1: 创建 Notification Channel(仅限 Android Oreo (API 26) 及以上版本)

为了确保通知在 Android Oreo 及以上版本中正常工作,你需要创建一个 Notification Channel。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channelName = "YourChannelName"val channelDescription = "YourChannelDescription"val channelId = "YourChannelId"val importance = NotificationManager.IMPORTANCE_DEFAULTval channel = NotificationChannel(channelId, channelName, importance).apply {description = channelDescription}// 注册通道val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagernotificationManager.createNotificationChannel(channel)
}

步骤 2: 创建自定义样式的通知

你可以使用 NotificationCompat.Builder 并利用其提供的样式,如 BigTextStyle, InboxStyle, BigPictureStyle 等来定制通知的视觉样式。

val builder = NotificationCompat.Builder(this, channelId) // 使用创建的通道ID.setSmallIcon(R.drawable.ic_notification) // 设置小图标.setContentTitle("Example Title") // 设置通知标题.setContentText("Example Description") // 设置通知内容.setPriority(NotificationCompat.PRIORITY_DEFAULT) // 设置优先级// 添加自定义样式.setStyle(NotificationCompat.BigTextStyle().bigText("Here is a longer text!"))// 构建 PendingIntent 来处理点击事件(例如打开 Activity)
val intent = Intent(this, YourActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)builder.setContentIntent(pendingIntent)
builder.setAutoCancel(true) // 点击通知后自动消失

这里,YourActivity::class.java 应该替换为你想要打开的 Activity 的实际类名。

步骤 3: 展示通知

最后,使用 NotificationManager 来展示你刚才创建的通知。不要忘记替换通知的 ID(notificationId),如果你想要展示多个通知,每个通知的 ID 都应该是独一无二的。

with(NotificationManagerCompat.from(this)) {// notificationId 是定义通知的唯一 int 值notify(notificationId, builder.build())
}

将以上步骤放在 onMessageReceived 方法内,这样每当你的应用接收到 FCM 消息时,都会展示一个定制化的通知。如果消息带有数据负载,你还可以根据这些数据来定制通知的内容和样式。

请注意,如果用户已经关闭了你的应用的通知权限,或者当前设备上的系统设置禁止了通知,那么这些通知将不会展示。因此,确保在应用中妥善地处理通知权限请求和指导用户如何在系统设置中启用通知。

如果您在处理 Firebase Cloud Messaging (FCM) 消息时正确配置了,通常不会出现两条通知的情况。这里是出现冲突可能情况的一些分析和建议:

1. FCM 通知类型

FCM 允许发送两种类型的消息:

  • 通知消息:当应用在后台时,消息会自动被 FCM 处理,显示为系统通知。如果应用在前台,onMessageReceived 会被调用,您有机会处理这个通知。
  • 数据消息:无论应用处于前台还是后台,onMessageReceived 都会被调用,您需要自己编写代码来生成并显示通知。

2. 消息处理

  • 当您的应用处于前台,并且收到了一个通知消息,您可以在 onMessageReceived 方法内自定义如何处理这个通知,包括展示自定义通知。
  • 当应用处于后台,并且收到了一个通知消息,系统会自动处理这个通知,展示一个系统通知。这种情况下,onMessageReceived 不会被调用。
  • 当应用处于前台或后台,并且收到了一个数据消息onMessageReceived 会被调用,您可以在其中处理数据并决定是否展示通知。

3. 避免冲突

如果您在前台手动处理并展示通知,同时您的消息是一个通知消息,可能会出现两个通知:一个是 FCM 自动创建的,一个是您自己创建的。为避免这种情况,有两种方法:

  • 使用数据消息:确保发送的是数据消息而非通知消息。这样,无论应用处于前台还是后台,onMessageReceived 都会被调用,而不会生成自动的系统通知,您可以在接收到消息时自由地处理并展示您自己的通知。
  • 合理设计通知显示逻辑:如果您需要发送通知消息(例如,确保后台应用也能接收),则可以在 onMessageReceived 里加入逻辑仅在应用处于前台时展示自定义通知。这样,当应用处于后台时,只有 FCM 生成的系统通知会被展示;当应用处于前台时,则根据您在 onMessageReceived 中的逻辑展示自定义通知。

总结

正确地选择和处理消息类型可以避免同时出现两条通知的问题。如果您完全控制通知的显示逻辑(尤其是选择数据消息),就可以按照自己的需求来设计通知的展示,而不会出现冲突。

重写 handleIntent(Intent intent) 方法来处理来自 Firebase Cloud Messaging (FCM) 的消息并不是官方推荐的方法,且很可能不解决您提出的问题。在 Firebase 的旧版本里,有些开发者通过重写 handleIntent 方法来在应用处于后台时截获和修改消息。然而,这种做法存在几个问题:

  1. 维护性和兼容性:直接重写基础服务的方法(如 handleIntent)可能导致在未来的库更新中出现兼容性问题。Firebase 和 Android 平台都在不断进化,直接依赖于这些内部实现的细节可能导致您的应用在未来某个时间点突然出现问题。

  2. 违背设计初衷:Firebase Messaging 设计的初衷是简化推送通知的处理。它区分了「通知消息」和「数据消息」,并为这两种类型的消息提供了不同的处理路径。通过恰当地使用这两种消息类型,您应该能够满足大部分的需求,而无需通过重写底层方法来实现特定的行为。

解决方案

如果您的目标是确保即使在应用处于后台或被杀死状态下也能按照自定义方式处理通知,您应该使用数据消息。发送数据消息而非通知消息,让您有机会在应用的 onMessageReceived 方法中捕获所有消息,并自定义如何处理这些消息和通知,无论应用处于前台还是后台。

当应用在后台或被杀死时收到数据消息,您可以在 onMessageReceived 方法中创建并显示自定义通知,这时可以使用 Android 的标准通知构建方法来自定义通知的展示。

确保在您的消息发送逻辑中,使用了数据消息。例如:

{"to": "device_token_or_topic","data": {"key1": "value1","key2": "value2",// 更多自定义的键值对}
}

在 Android 客户端,您的 FirebaseMessagingServiceonMessageReceived 方法将接收到这些消息,即使在应用被杀死的情况下也是如此:

override fun onMessageReceived(remoteMessage: RemoteMessage) {// Handle data payloadif (remoteMessage.data.isNotEmpty()) {val myData = remoteMessage.data["key1"] // 例子// 根据接收到的数据处理逻辑// 比如,生成自定义通知}
}

通过这种方式,您可以完全控制通知的生成和展示逻辑,而不需要依赖于 Firebase 自动处理通知的机制,这样就不会产生重复的通知,也避免了需要重写 handleIntent 方法的需求。

这篇关于Android firebase消息推送集成 FCM消息处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1006137

相关文章

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin