Firebase 通知的行為會因接收應用程式的前景/背景狀態而異。如要讓前景應用程式接收通知訊息或資料訊息,您需要編寫程式碼來處理 onMessageReceived
回呼。如要瞭解通知訊息和資料訊息的差異,請參閱「訊息類型」。
處理訊息
如要接收訊息,請使用擴充
FirebaseMessagingService
的服務。
您的服務應覆寫 onMessageReceived
和 onDeletedMessages
回呼。
視呼叫 onMessageReceived
前發生的延遲情況 (包括 OS 延遲、應用程式啟動時間、主執行緒遭其他作業阻斷,或先前呼叫 onMessageReceived
的時間過長),處理訊息的時間可能少於 20 秒。之後,Android 的程序終止或 Android O 的
背景執行限制等各種 OS 行為,可能會干擾您完成工作。
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
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 則),或是裝置超過一個月未連線至 FCM,就會發生這種情況。在這些情況下,您可能會收到 FirebaseMessagingService.onDeletedMessages()
的回呼。應用程式執行個體收到這項回呼時,應與應用程式伺服器進行完整同步。如果過去 4 週內未透過該裝置傳送訊息給 FCM,FCM 就不會撥打電話給 onDeletedMessages()
。
處理背景應用程式中的通知訊息
當應用程式在背景執行時,Android 會將通知訊息導向系統匣。使用者輕觸通知後,系統預設會開啟應用程式啟動器。
包括同時含有通知和資料酬載的訊息 (以及從「通知」控制台傳送的所有訊息)。在這些情況下,通知會傳送到裝置的系統匣,資料酬載則會傳送到啟動器 Activity 的 Intent 額外內容中。
如要深入瞭解訊息傳送至應用程式的情況,請參閱 FCM報表資訊主頁,其中會記錄在 Apple 和 Android 裝置上傳送及開啟的訊息數量,以及 Android 應用程式的「曝光次數」(使用者看到的通知) 資料。
在直接啟動模式下接收 FCM 訊息
開發人員可以讓 Android 應用程式在裝置處於直接啟動模式時接收訊息,即使裝置尚未解鎖,也能將 FCM 訊息傳送至應用程式。舉例來說,您可能希望應用程式使用者即使在裝置鎖定時,也能收到鬧鐘通知。
建構這個用途時,請遵守直接啟動模式的一般最佳做法和限制。請特別注意啟用直接啟動功能的訊息可見度,因為任何有權存取裝置的使用者,都能在不輸入使用者憑證的情況下查看這些訊息。
事前準備
- 裝置必須設為直接啟動模式。
- 裝置必須安裝最新版本的 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
也必須支援直接啟動模式 (在直接啟動模式下無法存取受憑證保護的儲存空間)。
如要瞭解如何傳送訊息給處於直接啟動模式的裝置,請參閱「傳送啟用直接啟動功能的訊息」。