| 選取平台: | iOS+ Android 網頁 Flutter Unity C++ |
本指南說明如何在 Android 用戶端應用程式中開始使用 Firebase Cloud Messaging,以便穩定傳送訊息。
FCM 用戶端必須使用搭載 Android 6.0 以上版本,且已安裝 Google Play 商店應用程式的裝置,或是以 Google API 執行 Android 6.0 的模擬器。請注意,您不一定要透過 Google Play 商店部署 Android 應用程式。
設定 SDK
如果尚未新增,請將 Firebase 新增至 Android 專案。
為獲得最佳 FCM 體驗,強烈建議在專案中啟用 Google Analytics。Google Analytics 是 FCM 的郵件傳送報告必要條件。
編輯應用程式資訊清單
在應用程式的資訊清單中新增下列內容:
- 擴充
FirebaseMessagingService的服務。如果您想在應用程式於背景執行時,接收通知以外的訊息,就必須執行這項操作。如要在前景應用程式中接收通知、接收資料酬載等,您必須擴充這項服務。 - (選用) 應用程式元件中的中繼資料元素,可設定預設通知圖示和顏色。如果傳入的訊息未明確設定圖示或顏色,Android 就會使用這些值。
- (選用) 從 Android 8.0 (API 級別 26) 以上版本開始,系統支援並建議使用
通知管道。FCM 提供具有基本設定的預設通知管道。如要建立及使用自己的預設管道,請將
default_notification_channel_id設為通知管道物件的 ID,如圖所示;每當傳入訊息未明確設定通知管道時,FCM 就會使用這個值。詳情請參閱「 管理通知管道」。
<service android:name=".java.MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
<!-- 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" />
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id" />
在 Android 13 以上版本要求執行階段通知權限
Android 13 導入了新的執行階段權限,可顯示通知。這項異動會影響在 Android 13 以上版本上執行的所有應用程式,這些應用程式都會使用FCM通知。
根據預設,FCM SDK (23.0.6 以上版本) 包含資訊清單中定義的 POST_NOTIFICATIONS 權限。不過,您的應用程式也需要使用常數 android.permission.POST_NOTIFICATIONS,要求這個權限的執行階段版本。使用者授予這項權限後,應用程式才能顯示通知。
如要要求新的執行階段權限,請按照下列步驟操作:
Kotlin
// Declare the launcher at the top of your Activity/Fragment: private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission(), ) { isGranted: Boolean -> if (isGranted) { // FCM SDK (and your app) can post notifications. } else { // TODO: Inform user that that your app will not show notifications. } } private fun askNotificationPermission() { // This is only necessary for API level >= 33 (TIRAMISU) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED ) { // FCM SDK (and your app) can post notifications. } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) { // TODO: display an educational UI explaining to the user the features that will be enabled // by them granting the POST_NOTIFICATION permission. This UI should provide the user // "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission. // If the user selects "No thanks," allow the user to continue without notifications. } else { // Directly ask for the permission requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) } } }
Java
// Declare the launcher at the top of your Activity/Fragment: private final ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { // FCM SDK (and your app) can post notifications. } else { // TODO: Inform user that that your app will not show notifications. } }); private void askNotificationPermission() { // This is only necessary for API level >= 33 (TIRAMISU) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) { // FCM SDK (and your app) can post notifications. } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) { // TODO: display an educational UI explaining to the user the features that will be enabled // by them granting the POST_NOTIFICATION permission. This UI should provide the user // "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission. // If the user selects "No thanks," allow the user to continue without notifications. } else { // Directly ask for the permission requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); } } }
一般來說,您應顯示 UI,向使用者說明授予應用程式發布通知的權限後,會啟用哪些功能。這個使用者介面應提供同意或拒絕選項,例如「確定」和「不用了」按鈕。如果使用者選取「確定」,請直接要求權限。 如果使用者選取「不用了,謝謝」,請允許使用者在不接收通知的情況下繼續。
如要進一步瞭解應用程式何時應向使用者要求 POST_NOTIFICATIONS 權限,請參閱「通知執行階段權限」一文中的最佳做法。
目標為 Android 12L (API 級別 32) 以下版本的應用程式通知權限
只要應用程式在前台運作,Android 就會在應用程式首次建立通知管道時,自動要求使用者授予權限。不過,建立管道和要求權限的時間有重要注意事項:
- 如果應用程式在背景執行時建立第一個通知管道 (FCM SDK 收到 FCM 通知時會這麼做),Android 不會允許顯示通知,也不會提示使用者授予通知權限,直到下次開啟應用程式時才會提示。也就是說,如果使用者在開啟應用程式並接受權限前收到通知,這些通知就會遺失。
- 我們強烈建議您更新應用程式,以 Android 13 以上版本為目標,充分運用平台 API 要求權限。如果無法這麼做,應用程式應先建立通知管道,再傳送任何通知給應用程式,以便觸發通知權限對話方塊,確保不會遺失任何通知。詳情請參閱通知權限最佳做法。
選用步驟:移除 POST_NOTIFICATIONS 權限
根據預設,FCM SDK 包含 POST_NOTIFICATIONS 權限。如果您的應用程式未使用通知訊息 (無論是透過 FCM 通知、其他 SDK,還是直接由應用程式發布),且您不希望應用程式包含這項權限,可以使用資訊清單合併工具的 remove 標記移除權限。請注意,移除這項權限後,系統會禁止顯示所有通知,而不只是 FCM 通知。在應用程式的資訊清單檔案中加入下列內容:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" tools:node="remove"/>
存取 Firebase 安裝 ID
應用程式首次啟動時,FCM SDK 會向 FCM 註冊應用程式例項,並傳回應用程式例項的 ID。如要指定個別應用程式例項,您需要擴充
FirebaseMessagingService 並覆寫
onRegistered(),藉此存取這個 ID。
最佳做法是擷取最新更新的 ID,因為 ID 可能會在初始啟動後輪替。
透過 Firebase 安裝 ID 啟用註冊
如要使用 Firebase 安裝 ID (FID) 透過 FCM 註冊應用程式執行個體,請在AndroidManifest.xml 檔案中新增下列中繼資料標記:
<meta-data android:name="firebase_messaging_installation_id_enabled" android:value="true" />
實作 onRegistered() 回呼
應用程式執行個體向 FCM 註冊後,系統就會使用 Firebase 安裝 ID (FID) 指定目標。如要在註冊時擷取 FID,請實作
onRegistered() 回呼。
註冊應用程式例項後,FCM SDK 會自動監控 FID 變更,並在偵測到變更時叫用回呼。
啟用自動初始化後,FCM SDK 會自動與 FCM 後端同步,確保註冊資訊為最新狀態,並叫用回呼,確保應用程式伺服器擁有目前的 ID。為避免 FID 遺失或過時,每當觸發這個回呼時,您都應將 FID 傳送至應用程式伺服器。
Kotlin
/** * There are three scenarios when `onRegistered` is called: * 1) Every time a manual `register()` call finishes successfully * 2) Whenever the FID is changed and the app is re-registered with FCM via the new FID. * 3) Automatically on app startup or routine sync when auto-initialization is enabled. * Under #2, there are three scenarios when the existing FID is changed: * A) App is restored to a new device * B) User uninstalls/reinstalls the app * C) User clears app data */ override fun onRegistered(installationId: String) { Log.d(TAG, "Registered installation ID: $installationId") // Send the Firebase Installation ID to your app server. sendRegistrationToServer(installationId) }
Java
/** * There are three scenarios when `onRegistered` is called: * 1) Every time a manual `register()` call finishes successfully * 2) Whenever the FID is changed and the app is re-registered with FCM via the new FID * 3) Automatically on app startup or routine sync when auto-initialization is enabled. * Under #2, there are three scenarios when the existing FID is changed: * A) App is restored to a new device * B) User uninstalls/reinstalls the app * C) User clears app data */ @Override public void onRegistered(@NonNull String installationId) { Log.d(TAG, "Registered installation ID: " + installationId); // Send the Firebase Installation ID to your app server. sendRegistrationToServer(installationId); }
停用自動初始化時,請手動註冊
如果必須停用自動初始化,FCM SDK 就不會在啟動時自動同步或觸發
onRegistered() 回呼。強烈建議您在授予通知權限後,重新啟用自動初始化。詳情請參閱「
重新啟用自動初始化」。
如果必須停用自動初始化,請在應用程式啟動時呼叫
FirebaseMessaging.getInstance().register(),透過
onRegistered() 回呼觸發註冊程序並傳送 FID。您可以在主要 Activity 的
onCreate() 方法中執行這項呼叫。
Kotlin
// Trigger manual registration if auto-initialization is turned off. // Consider calling this every time the app starts to guarantee sync status. FirebaseMessaging.getInstance().register() .addOnCompleteListener(this) { task -> if (!task.isSuccessful()) { // Registration failed. Consider retrying the registration with exponential backoff. Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception) } // Success! The Firebase Installation ID can be used to target messages to this app // instance and will be delivered asynchronously to your `onRegistered()` callback. }
Java
// Trigger manual registration if auto-initialization is turned off. // Consider calling this every time the app starts to guarantee sync status. FirebaseMessaging.getInstance().register() .addOnCompleteListener(task -> { if (!task.isSuccessful()) { // Registration failed. Consider retrying the registration with exponential backoff. Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception) } // Success! The Firebase Installation ID can be used to target messages to this app // instance and will be delivered asynchronously to your `onRegistered()` callback. });
存取 FCM 註冊權杖 (已淘汰)
應用程式首次啟動時,FCM SDK 會為用戶端應用程式例項產生註冊權杖。如要指定單一應用程式例項或建立裝置群組,您需要透過擴充
FirebaseMessagingService 並覆寫 onNewToken,存取這個權杖。由於權杖可能會在初始啟動後輪替,因此強烈建議您擷取最新的更新註冊權杖。
註冊權杖可能會在下列情況變更:
- 應用程式已還原到新裝置
- 使用者解除安裝/重新安裝應用程式
- 使用者清除應用程式資料。
擷取目前的註冊權杖
如要擷取目前權杖,請呼叫
FirebaseMessaging.getInstance().getToken():
Kotlin
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task -> if (!task.isSuccessful) { Log.w(TAG, "Fetching FCM registration token failed", task.exception) return@OnCompleteListener } // Get new FCM registration token val token = task.result // Log and toast val msg = getString(R.string.msg_token_fmt, token) Log.d(TAG, msg) Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() })
Java
FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(new OnCompleteListener<String>() { @Override public void onComplete(@NonNull Task<String> task) { if (!task.isSuccessful()) { Log.w(TAG, "Fetching FCM registration token failed", task.getException()); return; } // Get new FCM registration token String token = task.getResult(); // Log and toast String msg = getString(R.string.msg_token_fmt, token); Log.d(TAG, msg); Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } });
監控權杖產生作業
每當產生新權杖時,系統就會觸發 onNewToken 回呼。
Kotlin
/** * Called if the FCM registration token is updated. This may occur if the security of * the previous token had been compromised. Note that this is called when the * FCM registration token is initially generated so this is where you would retrieve the token. */ override fun onNewToken(token: String) { Log.d(TAG, "Refreshed token: $token") // If you want to send messages to this application instance or // manage this apps subscriptions on the server side, send the // FCM registration token to your app server. sendRegistrationToServer(token) }
Java
/** * There are two scenarios when onNewToken is called: * 1) When a new token is generated on initial app startup * 2) Whenever an existing token is changed * Under #2, there are three scenarios when the existing token is changed: * A) App is restored to a new device * B) User uninstalls/reinstalls the app * C) User clears app data */ @Override public void onNewToken(@NonNull String token) { Log.d(TAG, "Refreshed token: " + token); // If you want to send messages to this application instance or // manage this apps subscriptions on the server side, send the // FCM registration token to your app server. sendRegistrationToServer(token); }
取得權杖後,您可以將權杖傳送至應用程式伺服器,並使用偏好的方法儲存權杖。
檢查 Google Play 服務
如果應用程式使用 Play 服務 SDK,存取 Google Play 服務功能前,請務必先檢查裝置是否安裝相容的 Google Play 服務 APK。詳情請參閱「設定 Google Play 服務」一文。建議在兩個位置執行這項操作:主要活動的 onCreate() 方法,以及其 onResume() 方法。onCreate() 中的檢查可確保應用程式必須通過檢查才能使用。onResume() 中的檢查可確保使用者透過其他方式返回執行中的應用程式 (例如透過返回按鈕) 時,系統仍會執行檢查。
如果裝置沒有相容版本的 Google Play 服務,應用程式可以呼叫 GoogleApiAvailability.makeGooglePlayServicesAvailable(),讓使用者從 Play 商店下載 Google Play 服務。
防止自動初始化
產生 FCM 註冊時,程式庫會將 ID 和設定資料上傳至 Firebase。如要避免自動註冊,請將下列中繼資料值新增至 AndroidManifest.xml,停用 Analytics 收集功能和 FCM 自動初始化功能 (必須同時停用這兩項功能):
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" /> <meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />
重新啟用自動初始化
如要重新啟用 FCM 自動初始化功能,請進行執行階段呼叫:
Kotlin
Firebase.messaging.isAutoInitEnabled = true
Java
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
如要重新啟用 Analytics 收集功能,請呼叫 FirebaseAnalytics 類別的 setAnalyticsCollectionEnabled() 方法。例如:
setAnalyticsCollectionEnabled(true);
設定完成後,這些值會在應用程式重新啟動時保留。
傳送通知訊息
如要確認 Android 用戶端設定是否正確,請按照下列操作說明傳送測試通知訊息:
在目標裝置上安裝並執行應用程式。
確認裝置上的應用程式在背景執行。
在 Firebase 控制台中,依序前往「DevOps & Engagement」(DevOps 與參與度) >「Messaging」(訊息)
建立廣告活動。
如果這是您的第一則訊息:
選取「建立第一個廣告活動」。
選取「Firebase 通知訊息」,然後選取「建立」。
如果您先前已建立廣告活動:
在「廣告活動」分頁中,選取「新增廣告活動」。
按一下「通知」。
輸入訊息文字。其他欄位則為選填。
在右側窗格中選取「傳送測試訊息」。
在標示為「新增 FCM 註冊權杖」的欄位中,輸入您在本指南先前章節中取得的註冊權杖。
選取「測試」。
目標用戶端裝置應會收到通知,且應用程式必須在背景執行。
如要深入瞭解訊息傳送至應用程式的情形,請前往 Firebase 控制台的「DevOps 和參與度」>「訊息」>「報告」資訊主頁。這個資訊主頁會記錄在 Apple 和 Android 裝置上傳送及開啟的訊息數量,以及 Android 應用程式的「曝光次數」(使用者看到的通知) 資料。
後續步驟
完成設定步驟後,您可以選擇下列幾種方式,繼續使用 Android 版 FCM: