Firebase 通知的行為有所不同,具體取決於接收應用程序的前台/後台狀態。如果您希望前台應用程序接收通知消息或數據消息,則需要編寫代碼來處理onMessageReceived
回調。有關通知消息和數據消息之間差異的說明,請參閱消息類型。
處理消息
要接收消息,請使用擴展FirebaseMessagingService
服務。您的服務應該覆蓋onMessageReceived
和onDeletedMessages
回調。
處理消息的時間窗口可能會短於 20 秒,具體取決於調用onMessageReceived
之前發生的延遲,包括操作系統延遲、應用程序啟動時間、主線程被其他操作阻塞或之前的onMessageReceived
調用花費太長時間。此後,各種操作系統行為(例如 Android 的進程終止或 Android O 的後台執行限制)可能會干擾您完成工作的能力。
onMessageReceived
為大多數消息類型提供,但以下情況除外:
當您的應用程序處於後台時發送通知消息。在這種情況下,通知將傳遞到設備的系統托盤。默認情況下,用戶點擊通知會打開應用程序啟動器。
在後台接收時包含通知和數據負載的消息。在這種情況下,通知將傳遞到設備的系統托盤,數據負載將在啟動器活動的意圖的附加內容中傳遞。
總之:
應用程序狀態 | 通知 | 數據 | 兩個都 |
---|---|---|---|
前景 | 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對象執行操作並獲取消息數據:
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}") // Check if data needs to be processed by long running job if (needsToBeScheduled()) { // 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. }
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. }
覆蓋已onDeletedMessages
在某些情況下,FCM 可能不會傳遞消息。當特定設備上的應用程序在連接時有太多待處理消息 (>100) 或該設備超過 1 個月沒有連接到 FCM 時,就會發生這種情況。在這些情況下,您可能會收到FirebaseMessagingService.onDeletedMessages()
回調。當應用實例收到此回調時,它應該與您的應用服務器執行完全同步。如果您在過去 4 週內未向該設備上的應用發送消息,FCM 將不會調用onDeletedMessages()
。處理後台應用程序中的通知消息
當您的應用程序在後台運行時,Android 會將通知消息定向到系統托盤。默認情況下,用戶點擊通知會打開應用程序啟動器。
這包括包含通知和數據負載的消息(以及從通知控制台發送的所有消息)。在這些情況下,通知將傳遞到設備的系統托盤,並且數據負載將在啟動器活動的意圖的附加內容中傳遞。
要深入了解向您的應用程序發送的消息,請參閱FCM 報告儀表板,該儀表板記錄 Apple 和 Android 設備上發送和打開的消息數,以及 Android 應用程序的“印像數”(用戶看到的通知)數據。
在直接啟動模式下接收 FCM 消息
如果開發人員想要在設備解鎖之前向應用程序發送 FCM 消息,可以讓 Android 應用程序在設備處於直接啟動模式時接收消息。例如,您可能希望應用程序的用戶即使在鎖定的設備上也能收到警報通知。
構建此用例時,請遵守直接啟動模式的一般最佳實踐和限制。考慮直接啟動消息的可見性尤為重要;任何有權訪問該設備的用戶都可以查看這些消息,而無需輸入用戶憑據。
先決條件
- 設備必須設置為直接啟動模式。
- 設備必須安裝最新版本的 Google Play 服務(19.0.54 或更高版本)。
- 應用必須使用 FCM SDK (
com.google.firebase:firebase-messaging
) 才能接收 FCM 消息。
在您的應用程序中啟用直接啟動模式消息處理
在應用程序級 Gradle 文件中,添加對 FCM 直接啟動支持庫的依賴項:
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
通過在應用清單中添加
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
可以在直接啟動模式下運行非常重要。檢查是否滿足以下要求:
- 在直接啟動模式下運行時,服務不應訪問受憑據保護的存儲。
- 該服務不應嘗試使用在直接啟動模式下運行時未標記為直接啟動感知的組件,例如
Activities
、BroadcastReceivers
或其他Services
。 - 在直接啟動模式下運行時,該服務使用的任何庫也不得訪問受憑據保護的存儲,也不得調用非 directBootAware 組件。這意味著應用程序使用的從服務調用的任何庫要么需要直接啟動感知,要么應用程序需要檢查它是否在直接啟動模式下運行,而不是在該模式下調用它們。例如,Firebase SDK 支持直接啟動(它們可以包含在應用程序中,而不會在直接啟動模式下崩潰),但許多 Firebase API 不支持在直接啟動模式下調用。
- 如果應用程序使用自定義
Application
,則該Application
還需要具有直接啟動感知能力(在直接啟動模式下無法訪問受憑據保護的存儲)。
有關在直接啟動模式下向設備發送消息的指南,請參閱發送啟用直接啟動的消息。