Catch up on everthing we announced at this year's Firebase Summit. Learn more

在 Android 應用中接收消息

Firebase 通知的行為取決於接收應用的前台/後台狀態。如果你想前景化的應用程序接收通知消息或數據消息,你就需要編寫代碼來處理onMessageReceived回調。對於通知和數據消息之間的差異的解釋,請參見消息類型

處理消息

要接收郵件,使用擴展服務FirebaseMessagingService 。您的服務應覆蓋onMessageReceivedonDeletedMessages回調。它應該在收到後 20 秒內處理任何消息(Android Marshmallow 為 10 秒)。根據發生的提前調用OS延遲的時間窗口可能會短onMessageReceived 。此後,各種操作系統的行為如Android O公司後台執行限制可能與您完成您的工作能力。欲了解更多信息,請參閱我們的概述消息優先級

onMessageReceived提供了大多數的消息類型,但下列情況除外:

  • 當你的應用程序在後台發送通知消息。在這種情況下,通知將傳送到設備的系統托盤。默認情況下,用戶點擊通知會打開應用程序啟動器。

  • 消息既通知和數據有效載荷,在後台接收時。在這種情況下,通知被傳送到設備的系統托盤,數據有效負載被傳送到啟動器 Activity 的意圖的 extras 中。

總之:

應用狀態通知數據兩個都
前景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 顯示自定義默認圖標

  • 從發送的所有通知消息通知作曲家
  • 未在通知負載中明確設置圖標的任何通知消息。

Android 使用自定義默認顏色

  • 從發送的所有通知消息通知作曲家
  • 未在通知負載中明確設置顏色的任何通知消息。

如果未設置自定義默認圖標且未在通知負載中設置圖標,Android 將顯示呈現為白色的應用程序圖標。

覆蓋onMessageReceived

通過重載方法FirebaseMessagingService.onMessageReceived ,您可以執行基於接收到的上行動RemoteMessage對象並獲取消息數據:

爪哇

@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.
}

科特林+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報告信息中心,它記錄發送和“印象”(用戶看到通知)for Android應用程序打開蘋果和Android設備,伴隨數據的消息的數量。

後台受限應用(Android P 或更新版本)

FCM可能無法提供消息,向其中放入應用程序的背景限制由用戶(例如通過:設置- >應用程序和通知- > [APPNAME] - >電池)。一旦您的應用程序從後台限制中刪除,新消息將像以前一樣發送到應用程序。為了防止丟失的郵件和其他背景限制的影響,一定要避免由上市不良行為的Android命脈的努力。這些行為可能會導致 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. 使應用程序的FirebaseMessagingService直接引導意識到通過添加android:directBootAware="true"在應用程序清單屬性:

    <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也將需要直接開機知道(沒有獲得證書保護存儲在直接開機模式)。

有關在直接引導模式將消息發送到設備的指導,請直接發送啟用的引導的消息