获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

在 Android 应用中接收消息

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

Firebase 通知的行为因接收应用的前台/后台状态而异。如果您希望前台应用程序接收通知消息或数据消息,则需要编写代码来处理onMessageReceived回调。有关通知和数据消息之间区别的说明,请参阅消息类型

处理消息

要接收消息,请使用扩展FirebaseMessagingService的服务。您的服务应覆盖onMessageReceivedonDeletedMessages回调。它应该在收到后 20 秒内处理任何消息(Android Marshmallow 为 10 秒)。时间窗口可能会更短,具体取决于调用onMessageReceived之前发生的操作系统延迟。在那之后,各种操作系统行为(例如 Android O 的后台执行限制)可能会干扰您完成工作的能力。有关更多信息,请参阅我们的消息优先级概述。

大多数消息类型都提供了onMessageReceived ,但以下情况除外:

  • 当您的应用程序在后台时传递的通知消息。在这种情况下,通知将传送到设备的系统托盘。默认情况下,用户点击通知会打开应用启动器。

  • 在后台接收时带有通知和数据负载的消息。在这种情况下,通知被传递到设备的系统托盘,数据负载被传递到启动器 Activity 的附加内容中。

总之:

应用状态通知数据两个都
前景onMessageReceived onMessageReceived onMessageReceived
背景系统托盘onMessageReceived通知:系统托盘
数据:额外的意图。
有关消息类型的更多信息,请参阅通知和数据消息

编辑应用清单

要使用FirebaseMessagingService ,您需要在应用清单中添加以下内容:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

此外,建议您设置默认值以自定义通知的外观。您可以指定自定义默认图标和自定义默认颜色,只要未在通知有效负载中设置等效值,就会应用这些图标和自定义默认颜色。

application标签内添加这些行以设置自定义默认图标和自定义颜色:

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

Android 显示自定义默认图标

  • Notifications composer发送的所有通知消息。
  • 任何未在通知有效负载中明确设置图标的通知消息。

Android 使用自定义默认颜色

  • Notifications composer发送的所有通知消息。
  • 任何未在通知负载中明确设置颜色的通知消息。

如果未设置自定义默认图标且未在通知负载中设置图标,则 Android 会显示呈现为白色的应用程序图标。

覆盖onMessageReceived

通过覆盖FirebaseMessagingService.onMessageReceived方法,您可以根据接收到的RemoteMessage对象执行操作并获取消息数据:

Java

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    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());

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob();
        } else {
            // Handle message within 10 seconds
            handleNow();
        }

    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

Kotlin+KTX

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: ${remoteMessage.from}")

    // Check if message contains a data payload.
    if (remoteMessage.data.isNotEmpty()) {
        Log.d(TAG, "Message data payload: ${remoteMessage.data}")

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob()
        } else {
            // Handle message within 10 seconds
            handleNow()
        }
    }

    // Check if message contains a notification payload.
    remoteMessage.notification?.let {
        Log.d(TAG, "Message Notification Body: ${it.body}")
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

覆盖onDeletedMessages

在某些情况下,FCM 可能不会传递消息。如果您的应用在连接时在特定设备上等待处理的消息过多 (>100),或者如果该设备超过一个月未连接到 FCM,则会发生这种情况。在这些情况下,您可能会收到对FirebaseMessagingService.onDeletedMessages()的回调。当应用实例收到此回调时,它应该与您的应用服务器执行完全同步。如果您在过去 4 周内未向该设备上的应用发送消息,FCM 将不会调用onDeletedMessages()

在后台应用程序中处理通知消息

当您的应用程序处于后台时,Android 会将通知消息定向到系统托盘。默认情况下,用户点击通知会打开应用启动器。

这包括同时包含通知和数据负载的消息(以及从通知控制台发送的所有消息)。在这些情况下,通知会被传递到设备的系统托盘,而数据负载会在启动器 Activity 的意图的附加部分中传递。

要深入了解向您的应用程序传递的消息,请参阅FCM 报告仪表板,它记录了在 Apple 和 Android 设备上发送和打开的消息数量,以及 Android 应用程序的“展示次数”(用户看到的通知)的数据。

后台受限应用(Android P 或更新版本)

FCM 可能不会向用户设置后台限制的应用程序发送消息(例如通过:设置 -> 应用程序和通知 -> [应用程序名称] -> 电池)。一旦您的应用程序从后台限制中删除,新消息将像以前一样传递到该应用程序。为了防止丢失消息和其他后台限制影响,请确保避免Android Vitals努力列出的不良行为。这些行为可能会导致 Android 设备向用户建议您的应用受后台限制。你的应用可以使用isBackgroundRestricted()检查它是否被后台限制。

在直接启动模式下接收 FCM 消息

想要在设备解锁之前就向应用发送 FCM 消息的开发人员可以让 Android 应用在设备处于直接启动模式时接收消息。例如,您可能希望应用程序的用户即使在锁定的设备上也能收到警报通知。

在构建此用例时,请遵守直接启动模式的一般最佳实践和限制。考虑直接启动消息的可见性尤为重要;任何有权访问设备的用户都可以查看这些消息,而无需输入用户凭据。

先决条件

  • 设备必须设置为直接启动模式。
  • 设备必须安装最新版本的 Google Play 服务(19.0.54 或更高版本)。
  • 应用必须使用 FCM SDK ( com.google.firebase:firebase-messaging ) 才能接收 FCM 消息。

在您的应用中启用直接启动模式消息处理

  1. 在应用级 Gradle 文件中,添加对 FCM 直接启动支持库的依赖:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. 通过在应用清单中添加android:directBootAware="true"属性,使应用的FirebaseMessagingService直接启动感知:

    <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false"
        android:directBootAware="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    

确保此FirebaseMessagingService可以在直接启动模式下运行非常重要。检查以下要求:

  • 在直接启动模式下运行时,该服务不应访问受凭据保护的存储。
  • 服务不应尝试使用在直接启动模式下运行时未标记为直接启动感知的组件,例如ActivitiesBroadcastReceivers器或其他Services
  • 服务使用的任何库在直接启动模式下运行时也不得访问受凭证保护的存储,也不得调用非directBootAware 组件。这意味着应用程序使用的从服务调用的任何库都需要直接启动感知,或者应用程序需要检查它是否在直接启动模式下运行,而不是在该模式下调用它们。例如,Firebase SDK 可以直接启动(它们可以包含在应用程序中而不会在直接启动模式下崩溃),但许多 Firebase API 不支持在直接启动模式下调用。
  • 如果应用程序正在使用自定义Application ,则Application还需要直接启动感知(在直接启动模式下无法访问受凭证保护的存储)。

有关在直接启动模式下向设备发送消息的指南,请参阅发送支持直接启动的消息

,

Firebase 通知的行为因接收应用的前台/后台状态而异。如果您希望前台应用程序接收通知消息或数据消息,则需要编写代码来处理onMessageReceived回调。有关通知和数据消息之间区别的说明,请参阅消息类型

处理消息

要接收消息,请使用扩展FirebaseMessagingService的服务。您的服务应覆盖onMessageReceivedonDeletedMessages回调。它应该在收到后 20 秒内处理任何消息(Android Marshmallow 为 10 秒)。时间窗口可能会更短,具体取决于调用onMessageReceived之前发生的操作系统延迟。在那之后,各种操作系统行为(例如 Android O 的后台执行限制)可能会干扰您完成工作的能力。有关更多信息,请参阅我们的消息优先级概述。

大多数消息类型都提供了onMessageReceived ,但以下情况除外:

  • 当您的应用程序在后台时传递的通知消息。在这种情况下,通知将传送到设备的系统托盘。默认情况下,用户点击通知会打开应用启动器。

  • 在后台接收时带有通知和数据负载的消息。在这种情况下,通知被传递到设备的系统托盘,数据负载被传递到启动器 Activity 的附加内容中。

总之:

应用状态通知数据两个都
前景onMessageReceived onMessageReceived onMessageReceived
背景系统托盘onMessageReceived通知:系统托盘
数据:额外的意图。
有关消息类型的更多信息,请参阅通知和数据消息

编辑应用清单

要使用FirebaseMessagingService ,您需要在应用清单中添加以下内容:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

此外,建议您设置默认值以自定义通知的外观。您可以指定自定义默认图标和自定义默认颜色,只要未在通知有效负载中设置等效值,就会应用这些图标和自定义默认颜色。

application标签内添加这些行以设置自定义默认图标和自定义颜色:

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

Android 显示自定义默认图标

  • Notifications composer发送的所有通知消息。
  • 任何未在通知有效负载中明确设置图标的通知消息。

Android 使用自定义默认颜色

  • Notifications composer发送的所有通知消息。
  • 任何未在通知负载中明确设置颜色的通知消息。

如果未设置自定义默认图标且未在通知负载中设置图标,则 Android 会显示呈现为白色的应用程序图标。

覆盖onMessageReceived

通过覆盖FirebaseMessagingService.onMessageReceived方法,您可以根据接收到的RemoteMessage对象执行操作并获取消息数据:

Java

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    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());

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob();
        } else {
            // Handle message within 10 seconds
            handleNow();
        }

    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

Kotlin+KTX

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: ${remoteMessage.from}")

    // Check if message contains a data payload.
    if (remoteMessage.data.isNotEmpty()) {
        Log.d(TAG, "Message data payload: ${remoteMessage.data}")

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob()
        } else {
            // Handle message within 10 seconds
            handleNow()
        }
    }

    // Check if message contains a notification payload.
    remoteMessage.notification?.let {
        Log.d(TAG, "Message Notification Body: ${it.body}")
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

覆盖onDeletedMessages

在某些情况下,FCM 可能不会传递消息。如果您的应用在连接时在特定设备上等待处理的消息过多 (>100),或者如果该设备超过一个月未连接到 FCM,则会发生这种情况。在这些情况下,您可能会收到对FirebaseMessagingService.onDeletedMessages()的回调。当应用实例收到此回调时,它应该与您的应用服务器执行完全同步。如果您在过去 4 周内未向该设备上的应用发送消息,FCM 将不会调用onDeletedMessages()

在后台应用程序中处理通知消息

当您的应用程序处于后台时,Android 会将通知消息定向到系统托盘。默认情况下,用户点击通知会打开应用启动器。

这包括同时包含通知和数据负载的消息(以及从通知控制台发送的所有消息)。在这些情况下,通知会被传递到设备的系统托盘,而数据负载会在启动器 Activity 的意图的附加部分中传递。

要深入了解向您的应用程序传递的消息,请参阅FCM 报告仪表板,它记录了在 Apple 和 Android 设备上发送和打开的消息数量,以及 Android 应用程序的“展示次数”(用户看到的通知)的数据。

后台受限应用(Android P 或更新版本)

FCM 可能不会向用户设置后台限制的应用程序发送消息(例如通过:设置 -> 应用程序和通知 -> [应用程序名称] -> 电池)。一旦您的应用程序从后台限制中删除,新消息将像以前一样传递到该应用程序。为了防止丢失消息和其他后台限制影响,请确保避免Android Vitals努力列出的不良行为。这些行为可能会导致 Android 设备向用户建议您的应用受后台限制。你的应用可以使用isBackgroundRestricted()检查它是否被后台限制。

在直接启动模式下接收 FCM 消息

想要在设备解锁之前就向应用发送 FCM 消息的开发人员可以让 Android 应用在设备处于直接启动模式时接收消息。例如,您可能希望应用程序的用户即使在锁定的设备上也能收到警报通知。

在构建此用例时,请遵守直接启动模式的一般最佳实践和限制。考虑直接启动消息的可见性尤为重要;任何有权访问设备的用户都可以查看这些消息,而无需输入用户凭据。

先决条件

  • 设备必须设置为直接启动模式。
  • 设备必须安装最新版本的 Google Play 服务(19.0.54 或更高版本)。
  • 应用必须使用 FCM SDK ( com.google.firebase:firebase-messaging ) 才能接收 FCM 消息。

在您的应用中启用直接启动模式消息处理

  1. 在应用级 Gradle 文件中,添加对 FCM 直接启动支持库的依赖:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. 通过在应用清单中添加android:directBootAware="true"属性,使应用的FirebaseMessagingService直接启动感知:

    <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false"
        android:directBootAware="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    

确保此FirebaseMessagingService可以在直接启动模式下运行非常重要。检查以下要求:

  • 在直接启动模式下运行时,该服务不应访问受凭据保护的存储。
  • 服务不应尝试使用在直接启动模式下运行时未标记为直接启动感知的组件,例如ActivitiesBroadcastReceivers器或其他Services
  • 服务使用的任何库在直接启动模式下运行时也不得访问受凭证保护的存储,也不得调用非directBootAware 组件。这意味着应用程序使用的从服务调用的任何库都需要直接启动感知,或者应用程序需要检查它是否在直接启动模式下运行,而不是在该模式下调用它们。例如,Firebase SDK 可以直接启动(它们可以包含在应用程序中而不会在直接启动模式下崩溃),但许多 Firebase API 不支持在直接启动模式下调用。
  • 如果应用程序正在使用自定义Application ,则Application还需要直接启动感知(在直接启动模式下无法访问受凭证保护的存储)。

有关在直接启动模式下向设备发送消息的指南,请参阅发送支持直接启动的消息