FCM 客户端需要在搭载 Android 5.0 或更高版本且安装了 Google Play 商店应用的设备上运行,或者在搭载 Android 5.0 版本且支持 Google API 的模拟器中运行。请注意,除了使用 Google Play 商店,您还可以通过其他方式部署您的 Android 应用。
设置 SDK
如果您已经为自己的应用启用了其他 Firebase 功能,那么可能已经完成了本部分将要介绍的一些任务。如果您还没这么做,请将 Firebase 添加到您的 Android 项目
修改您的应用清单
将以下内容添加至应用的清单中:
- 一项扩展
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); } } }
通常,您应向用户显示一个界面,说明如果用户授予应用发布通知的权限,会启用哪些功能。此界面应向用户提供同意或拒绝的选项,例如确定和不用了按钮。如果用户选择确定,则直接请求该权限。如果用户选择不用了,则允许用户在不接收通知的情况下继续操作。
如需详细了解有关您的应用应在何时向用户请求 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);
这些值一经设置,即使应用重启也将持续生效。
后续步骤
客户端应用设置完成后,您就可以使用 Notifications Composer 开始发送下行消息。您可以下载、运行和查看此功能的快速入门示例。
如需向您的应用添加其他更高级的行为,您可以声明 intent 过滤器,并实现一个 Activity 来响应传入的消息。如需了解详情,请参阅有关从应用服务器发送消息的指南:
请注意,如需使用这些功能,您需要完成服务器实现和使用服务器协议(HTTP 或 XMPP),或者实现 Admin SDK。