Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

在 Android 上設置 Firebase 雲消息傳遞客戶端應用

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

FCM 客戶端需要運行 Android 4.4 或更高版本並安裝了 Google Play 商店應用程序的設備,或運行 Android 4.4 和 Google API 的模擬器。請注意,您不僅限於通過 Google Play 商店部署您的 Android 應用程序。

設置 SDK

如果您已經為您的應用啟用了其他 Firebase 功能,本部分將介紹您可能已完成的任務。如果您還沒有,請將 Firebase 添加到您的 Android 項目中

編輯您的應用清單

將以下內容添加到應用的清單中:

  • 擴展FirebaseMessagingService的服務。如果您想要在後台接收應用程序通知之外的任何消息處理,這是必需的。要在前台應用程序中接收通知、接收數據負載、發送上游消息等,您必須擴展此服務。
  • <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
  • (可選)在應用程序組件內,元數據元素設置默認通知圖標和顏色。只要傳入的消息沒有明確設置圖標或顏色,Android 就會使用這些值。
  • <!-- 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 8.0(API 級別 26)及更高版本開始,支持並推薦通知通道。 FCM 提供具有基本設置的默認通知通道。如果您更喜歡創建和使用自己的默認頻道,請將default_notification_channel_id設置為您的通知頻道對象的 ID,如圖所示;只要傳入消息未明確設置通知通道,FCM 就會使用此值。要了解更多信息,請參閱管理通知渠道
  • <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請求此權限的運行時版本。在用戶授予此權限之前,您的應用將無法顯示通知。

請求新的運行時權限:

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);
        }
    }
}

Kotlin+KTX

// 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)
        }
    }
}

通常,您應該顯示一個 UI,向用戶解釋如果他們授予應用程序發布通知的權限將啟用的功能。此 UI 應為用戶提供同意或拒絕的選項,例如OKNo Thanks按鈕。如果用戶選擇OK ,直接請求權限。如果用戶選擇No Thanks ,則允許用戶在沒有通知的情況下繼續。

有關您的應用何時應向用戶請求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"/>

訪問設備註冊令牌

在您的應用程序首次啟動時,FCM SDK 會為客戶端應用程序實例生成一個註冊令牌。如果您想定位單個設備或創建設備組,您需要通過擴展FirebaseMessagingService並覆蓋onNewToken來訪問此令牌。

本節介紹如何檢索令牌以及如何監視對令牌的更改。由於初始啟動後令牌可能會輪換,因此強烈建議您檢索最新更新的註冊令牌。

註冊令牌可能會在以下情況下更改:

  • 該應用程序已在新設備上恢復
  • 用戶卸載/重新安裝應用程序
  • 用戶清除應用數據。

檢索當前註冊令牌

當您需要檢索當前令牌時,請調用FirebaseMessaging.getInstance().getToken()

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();
        }
    });

Kotlin+KTX

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()
})

監控令牌生成

每當生成新令牌時都會觸發onNewToken回調。

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);
}

Kotlin+KTX

/**
 * 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)
}

獲取令牌後,您可以將其發送到您的應用服務器並使用您喜歡的方法進行存儲。

檢查 Google Play 服務

依賴 Play 服務 SDK 的應用應始終在訪問 Google Play 服務功能之前檢查設備是否有兼容的 Google Play 服務 APK。建議在兩個地方執行此操作:在主活動的onCreate()方法中,以及在其onResume()方法中。 onCreate()中的檢查確保在沒有成功檢查的情況下無法使用應用程序。 onResume()中的檢查確保如果用戶通過其他方式(例如通過後退按鈕)返回到正在運行的應用程序,仍會執行檢查。

如果設備沒有兼容版本的 Google Play 服務,您的應用可以調用GoogleApiAvailability.makeGooglePlayServicesAvailable()以允許用戶從 Play 商店下載 Google Play 服務。

防止自動初始化

生成 FCM 註冊令牌時,庫會將標識符和配置數據上傳到 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 自動初始化,請進行運行時調用:

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

Kotlin+KTX

Firebase.messaging.isAutoInitEnabled = true

要重新啟用 Analytics 收集,請調用FirebaseAnalytics類的setAnalyticsCollectionEnabled()方法。例如:

setAnalyticsCollectionEnabled(true);

設置後,這些值會在應用重新啟動後持續存在。

下一步

設置客戶端應用程序後,您就可以開始使用Notifications composer發送下游消息了。快速入門示例中演示了此功能,您可以下載、運行和查看該示例。

要向您的應用程序添加其他更高級的行為,您可以聲明一個意圖過濾器並實現一個活動來響應傳入的消息。詳情請參見從應用服務器發送消息的指南:

請記住,要利用這些功能,您需要一個服務器實現和服務器協議(HTTP 或 XMPP),或者Admin SDK的實現。