Firebase Cloud Messaging (FCM) 是 Google 提供的跨平台消息推送解决方案。以下是在 Android Kotlin 项目中集成 FCM 的详细步骤。
一、前期准备
1. 创建 Firebase 项目
- 访问 Firebase 控制台
- 点击"添加项目",按照向导创建新项目
- 项目创建完成后,点击"添加应用"选择 Android 应用
2. 获取配置文件
- 输入应用的包名(必须与
build.gradle
中的applicationId
一致) - 下载
google-services.json
文件 - 将该文件放到项目的
app
模块根目录下
二、项目配置
1. 项目级 build.gradle
// 在项目级的 build.gradle 文件中添加:
buildscript {
dependencies {
// 添加 Google Services 插件
classpath 'com.google.gms:google-services:4.3.15'
}
}
2. 应用级 build.gradle
// 在应用级的 build.gradle 文件顶部添加:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.gms.google-services' // 添加这行
}
dependencies {
// FCM 核心库
implementation 'com.google.firebase:firebase-messaging:23.2.1'
// 可选 - Kotlin 协程支持
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4'
// 可选 - 用于处理后台消息
implementation 'androidx.work:work-runtime-ktx:2.8.1'
}
三、实现 FCM 服务
1. 创建自定义 FirebaseMessagingService
import android.util.Log
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val TAG = "FCM_Service"
/**
* 当收到新消息时调用
*/
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: ${remoteMessage.from}")
// 检查消息是否包含数据负载
if (remoteMessage.data.isNotEmpty()) {
Log.d(TAG, "Message data payload: ${remoteMessage.data}")
// 在这里处理数据消息
handleDataMessage(remoteMessage.data)
}
// 检查消息是否包含通知负载
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
// 在这里处理通知消息
handleNotification(it)
}
}
/**
* 当新令牌生成时调用
*/
override fun onNewToken(token: String) {
Log.d(TAG, "Refreshed token: $token")
// 将新令牌发送到你的应用服务器
sendRegistrationToServer(token)
}
private fun handleDataMessage(data: Map<String, String>) {
// 实现你的数据消息处理逻辑
// 例如:更新UI、显示通知等
}
private fun handleNotification(notification: RemoteMessage.Notification) {
// 实现你的通知处理逻辑
// 例如:显示系统通知
}
private fun sendRegistrationToServer(token: String) {
// 实现将令牌发送到你的应用服务器的逻辑
}
}
2. 在 AndroidManifest.xml 中注册服务
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
四、获取设备令牌
1. 创建 FCM 管理器类
import android.util.Log
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.tasks.await
object FCMManager {
private const val TAG = "FCM_Manager"
/**
* 获取当前 FCM 令牌
*/
suspend fun getToken(): String? {
return try {
FirebaseMessaging.getInstance().token.await().also { token ->
Log.d(TAG, "FCM Token: $token")
}
} catch (e: Exception) {
Log.e(TAG, "Failed to get FCM token", e)
null
}
}
/**
* 订阅主题
*/
fun subscribeToTopic(topic: String) {
FirebaseMessaging.getInstance().subscribeToTopic(topic)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "Subscribed to $topic")
} else {
Log.e(TAG, "Subscribe to $topic failed", task.exception)
}
}
}
/**
* 取消订阅主题
*/
fun unsubscribeFromTopic(topic: String) {
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "Unsubscribed from $topic")
} else {
Log.e(TAG, "Unsubscribe from $topic failed", task.exception)
}
}
}
}
2. 在应用启动时获取令牌
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 获取 FCM 令牌
lifecycleScope.launch {
val token = FCMManager.getToken()
// 可以将 token 发送到你的服务器
}
// 订阅主题示例
FCMManager.subscribeToTopic("news")
}
}
五、处理通知点击
1. 创建通知点击处理 Activity
class NotificationHandlerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification_handler)
// 处理从通知传递过来的数据
intent.extras?.let { extras ->
// 解析 extras 中的数据并处理
val message = extras.getString("key")
// 根据消息内容跳转到相应页面
}
// 关闭 Activity(如果是仅用于处理点击)
finish()
}
}
2. 在 AndroidManifest.xml 中配置
<activity
android:name=".NotificationHandlerActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.Translucent">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
六、测试 FCM 功能
1. 使用 Firebase 控制台测试
- 在 Firebase 控制台中选择你的项目
- 进入 Cloud Messaging 部分
- 点击"发送第一条消息"
- 填写通知标题、内容等
- 选择目标设备或主题
- 发送测试消息
2. 使用 cURL 命令测试
curl -X POST \
'https://fcm.googleapis.com/fcm/send' \
-H 'Authorization: key=YOUR_SERVER_KEY' \
-H 'Content-Type: application/json' \
-d '{
"to": "DEVICE_TOKEN",
"notification": {
"title": "测试通知",
"body": "这是一条测试消息",
"click_action": ".NotificationHandlerActivity"
},
"data": {
"key1": "value1",
"key2": "value2"
}
}'
七、常见问题解决
-
收不到通知:
- 检查设备是否联网
- 确认
google-services.json
配置正确 - 检查应用是否被强制停止
-
令牌获取失败:
- 确保 Google Play 服务可用
- 检查设备是否支持 GMS
-
后台消息不触发:
- 确认服务已在 Manifest 中正确声明
- 检查 Android 版本是否限制了后台服务
-
通知图标不显示:
- 确保有默认通知图标
- 在 Manifest 中添加元数据:
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification" />
八、最佳实践
-
令牌管理:
- 每次应用启动时检查令牌
- 在
onNewToken
中及时更新服务器上的令牌
-
消息处理:
- 区分数据消息和通知消息
- 对于重要消息,考虑添加 WorkManager 任务确保处理
-
用户体验:
- 为通知设置合适的渠道
- 提供清晰的点击行为
-
安全性:
- 使用 HTTPS 传输令牌
- 在服务器端验证消息来源
通过以上步骤,你的 Android Kotlin 应用已经成功集成了 FCM 推送通知功能。你可以根据需要进一步扩展功能,如实现富媒体通知、分组通知等高级特性。