You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需Cloud Functions实现Android端Firebase设备间推送通知

Android端FCM设备间推送实现方案(无付费Cloud Functions+不暴露Server Key)

核心思路是借助Firebase实时数据库/Cloud Firestore作为消息中转层,利用数据库的实时监听能力触发本地通知,全程无需调用FCM服务器端API(也就不需要Server Key),同时通过安全规则保障数据访问权限。

1. 配置数据库安全规则

首先要限制消息节点的读写权限,确保只有对应UID的用户能访问自己的消息队列,避免越权操作。

Realtime Database规则示例

{
  "rules": {
    "user_messages": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    },
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid || auth != null",
        ".write": "$uid === auth.uid"
      }
    }
  }
}
  • user_messages/$uid:仅当前用户可读写自己的消息队列
  • users/$uid:允许其他用户读取公开信息(比如设备令牌),但仅本人可修改

2. 设备令牌存储(可选但实用)

让用户登录后将自己的FCM设备令牌存入数据库,方便后续扩展(比如离线消息处理):

FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val token = task.result ?: return@addOnCompleteListener
        val currentUid = FirebaseAuth.getInstance().currentUser?.uid ?: return@addOnCompleteListener
        FirebaseDatabase.getInstance().getReference("users/$currentUid/fcm_token")
            .setValue(token)
    }
}

3. 发送方:写入消息到接收方队列

发送方只需将消息内容写入接收方的专属消息节点,无需直接调用FCM推送API:

val senderUid = FirebaseAuth.getInstance().currentUser?.uid ?: return
val receiverUid = "目标用户UID"
val messageData = hashMapOf(
    "senderUid" to senderUid,
    "title" to "好友消息",
    "content" to "这是设备间直接推送的内容",
    "timestamp" to System.currentTimeMillis()
)

// 写入接收方的消息队列
FirebaseDatabase.getInstance().getReference("user_messages/$receiverUid")
    .push()
    .setValue(messageData)
    .addOnSuccessListener {
        // 消息写入成功回调
    }
    .addOnFailureListener {
        // 处理写入失败
    }

4. 接收方:监听消息并触发本地通知

接收方监听自己的消息节点,一旦有新消息写入,直接调用Android本地通知API显示通知,全程不依赖FCM服务器下行推送:

val currentUid = FirebaseAuth.getInstance().currentUser?.uid ?: return
val messagesRef = FirebaseDatabase.getInstance().getReference("user_messages/$currentUid")

// 监听消息节点的新增事件
messagesRef.addChildEventListener(object : ChildEventListener {
    override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
        val message = snapshot.getValue(Message::class.java) ?: return
        // 显示本地通知
        showLocalNotification(message.title, message.content)
        // 可选:删除已处理的消息,避免重复通知
        snapshot.ref.removeValue()
    }

    // 实现其他接口方法(可留空)
    override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {}
    override fun onChildRemoved(snapshot: DataSnapshot) {}
    override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
    override fun onCancelled(error: DatabaseError) {}
})

// 本地通知实现
private fun showLocalNotification(title: String, content: String) {
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    // 创建通知渠道(Android O及以上必填)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            "DEVICE_PUSH_CHANNEL",
            "设备间推送",
            NotificationManager.IMPORTANCE_DEFAULT
        )
        notificationManager.createNotificationChannel(channel)
    }
    // 构建通知内容
    val intent = Intent(this, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    val notification = NotificationCompat.Builder(this, "DEVICE_PUSH_CHANNEL")
        .setContentTitle(title)
        .setContentText(content)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)
        .build()
    // 显示通知
    notificationManager.notify(System.currentTimeMillis().toInt(), notification)
}

// 消息数据类
data class Message(
    val senderUid: String? = null,
    val title: String? = null,
    val content: String? = null,
    val timestamp: Long? = null
)

核心优势

  • 无付费成本:利用Firebase数据库免费额度即可满足小型应用需求
  • 无Server Key暴露风险:全程使用Firebase客户端SDK操作,无需调用FCM服务器端API
  • 安全可控:通过数据库规则严格限制消息访问权限,避免数据泄露

内容的提问来源于stack exchange,提问作者lanezalbryt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 04:54:24