| 選取平台: | iOS+ Android Web Flutter Unity C++ |
本指南說明如何在 Android 用戶端應用程式中開始使用 Firebase Cloud Messaging,以便可靠地傳送訊息。
FCM 用戶端需要搭載 Android 7.0 以上版本,且已安裝 Google Play 商店應用程式的裝置,或搭載 Android 7.0 且具備 Google API 的模擬器。請注意,您不一定要透過 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,向使用者說明授予應用程式通知權限後,會啟用哪些功能。這個 UI 應提供使用者同意或拒絕的選項,例如「確定」和「不用了,謝謝」按鈕。如果使用者選取「OK」,請直接要求權限。如果使用者選取「不用了,謝謝」,請允許使用者在不接收通知的情況下繼續操作。
如要進一步瞭解應用程式何時應向使用者要求 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 服務 APK,再存取 Google Play 服務功能。詳情請參閱「設定 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」(開發運作與參與度) > 「Messaging」(訊息)
建立廣告活動。
如果這是您的第一則訊息:
選取「建立第一個廣告活動」。
依序選取「Firebase 通知訊息」和「建立」。
如果您先前已建立廣告活動:
在「廣告活動」分頁中,選取「新增廣告活動」。
按一下「通知」。
輸入訊息文字。其他欄位均為選填。
在右側窗格中選取「傳送測試訊息」。
在「Add an FCM registration token」(新增 FCM 註冊權杖) 欄位中,輸入您在本指南前一節取得的註冊權杖。
選取「測試」。
目標用戶端裝置應會收到通知,且應用程式會在背景執行。
如要深入瞭解應用程式的訊息傳遞情形,請前往 Firebase 控制台的「DevOps & Engagement」 >「Messaging」 >「Reports」資訊主頁。這個資訊主頁會記錄在 Apple 和 Android 裝置上傳送及開啟的訊息數量,以及 Android 應用程式的「曝光」資料 (使用者看到的通知)。
後續步驟
完成設定步驟後,您可以選擇下列幾種方式,繼續使用 Android 版 FCM: