Firebase Cloud Messaging 使用入门


本快速入门介绍了如何在移动和 Web 客户端应用中设置 Firebase Cloud Messaging,以便您能够可靠地发送消息。对于服务器环境,请参阅您的服务器环境和 FCM

Firebase Cloud Messaging 和 Android 使用入门

FCM 客户端需要在搭载 Android 5.0 或更高版本且安装了 Google Play 商店应用的设备上运行,或者在搭载 Android 5.0 版本且支持 Google API 的模拟器中运行。请注意,除了使用 Google Play 商店,您还可以通过其他方式部署您的 Android 应用。

设置 SDK

将 Firebase 添加到您的 Android 项目(如果尚未添加)。

为了获得最佳的 FCM 使用体验,我们强烈建议您在项目中启用 Google AnalyticsFCM消息传送报告功能需要使用 Google Analytics

修改您的应用清单

将以下内容添加至应用的清单中:

  • 一项扩展 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 请求此权限的运行时版本。在用户授予此权限之前,您的应用将无法显示通知。

如需请求该项新运行时权限,请执行以下操作:

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

通常,您应向用户显示一个界面,说明如果用户授予应用发布通知的权限,会启用哪些功能。此界面应向用户提供同意或拒绝的选项,例如确定不用了按钮。如果用户选择确定,则直接请求该权限。如果用户选择不用了,则允许用户在不接收通知的情况下继续操作。

如需详细了解有关您的应用应在何时向用户请求 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()

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。我们建议您在以下两个位置进行检查:主 Activity 的 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 自动初始化功能,请执行运行时调用:

Kotlin

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

如需重新启用 Analytics 数据收集,请调用 FirebaseAnalytics 类的 setAnalyticsCollectionEnabled() 方法。例如:

setAnalyticsCollectionEnabled(true);

这些值一经设置,即使应用重启也将持续生效。

发送通知消息

如需确保 Android 客户端设置正确,您可以按照以下说明发送测试通知消息:

  1. 在目标设备上安装并运行该应用。
  2. 确保应用在设备的后台中运行。
  3. Firebase 控制台中,打开消息传递页面。
  4. 如果这是您的第一条消息,请依次选择制作首个宣传活动Firebase 通知消息创建
  5. 否则,请在宣传活动标签页上选择新建宣传活动,然后选择通知
  6. 输入消息内容。所有其他字段都是选填字段。
  7. 从右侧窗格中选择发送测试消息
  8. 在标签为添加 FCM 注册令牌的字段中,输入您根据本指南的前一部分获得的注册令牌。
  9. 选择测试

目标客户端设备(应用在其后台运行)应该会接收到通知。

如需详细了解发送到您应用的消息,请参阅 FCM 报告信息中心。该信息中心会记录在 Apple 和 Android 设备上发送和打开的消息数量,以及 Android 应用的展示次数(用户看到的通知条数)数据。

后续步骤

客户端应用设置完成后,您就可以开始接收消息或向用户发送消息: