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

基于Firebase免费版实现Android Java聊天应用消息推送通知

基于Firebase免费方案实现Android聊天应用消息推送通知

核心思路

利用Firebase免费方案包含的Firebase Cloud Messaging(FCM)和Cloud Functions(Spark计划有免费额度),结合Realtime Database的监听能力,实现新消息触发推送通知的逻辑。


1. 配置Android端FCM依赖与设备令牌获取

确保Android项目已接入Firebase,在模块级build.gradle(通常是app/build.gradle)添加FCM依赖:

dependencies {
    implementation 'com.google.firebase:firebase-messaging:23.4.1'
}

获取设备FCM令牌(用于标识推送目标):

FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(task -> {
        if (!task.isSuccessful()) {
            Log.w("FCM_TOKEN", "获取令牌失败", task.getException());
            return;
        }
        String token = task.getResult();
        saveTokenToRealtimeDb(token); // 存储令牌到数据库(步骤2实现)
    });

2. 存储设备令牌到Realtime Database

将用户ID与设备令牌绑定存储,方便后续推送时查询目标设备。在Realtime Database的users节点下新增tokens子节点:

private void saveTokenToRealtimeDb(String token) {
    String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
    DatabaseReference tokenRef = FirebaseDatabase.getInstance().getReference("users/" + userId + "/tokens");
    tokenRef.child(token).setValue(true); // 用令牌本身作为key,避免重复存储
}

3. 编写Cloud Functions监听新消息并触发推送

Firebase Spark计划每月提供免费的Cloud Functions调用额度,足够小型应用使用。用Node.js编写函数监听Realtime Database的新消息写入,触发FCM推送。

3.1 初始化Cloud Functions

本地安装Firebase CLI后,在项目根目录执行firebase init functions,选择JavaScript作为开发语言。

3.2 编写推送逻辑

修改functions/index.js:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

// 监听messages节点的新消息写入事件
exports.sendNewMessageNotification = functions.database.ref('/messages/{messageId}')
    .onCreate(async (snapshot, context) => {
        const messageData = snapshot.val();
        const receiverId = messageData.receiverId; // 单聊接收方ID
        const groupId = messageData.groupId; // 群聊群组ID

        let targetTokens = [];

        if (receiverId) {
            // 单聊:查询接收方的所有设备令牌
            const tokenSnapshot = await admin.database().ref(`users/${receiverId}/tokens`).once('value');
            if (tokenSnapshot.exists()) {
                targetTokens = Object.keys(tokenSnapshot.val());
            }
        } else if (groupId) {
            // 群聊:查询群组所有成员的设备令牌
            const membersSnapshot = await admin.database().ref(`groups/${groupId}/members`).once('value');
            if (membersSnapshot.exists()) {
                const memberIds = Object.keys(membersSnapshot.val());
                for (const memberId of memberIds) {
                    const memberTokenSnapshot = await admin.database().ref(`users/${memberId}/tokens`).once('value');
                    if (memberTokenSnapshot.exists()) {
                        targetTokens.push(...Object.keys(memberTokenSnapshot.val()));
                    }
                }
            }
        }

        if (targetTokens.length === 0) {
            functions.logger.log("未找到目标设备令牌");
            return null;
        }

        // 构建FCM通知内容
        const payload = {
            notification: {
                title: "新消息提醒",
                body: "您收到一条消息",
                clickAction: "OPEN_CHAT_ACTIVITY" // 点击通知跳转的Activity
            },
            tokens: targetTokens
        };

        // 发送批量推送
        return admin.messaging().sendMulticast(payload)
            .then(response => {
                functions.logger.log(`成功推送 ${response.successCount} 条通知,失败 ${response.failureCount} 条`);
                return null;
            })
            .catch(error => {
                functions.logger.error("推送失败", error);
                return null;
            });
    });

3.3 部署Cloud Functions

执行firebase deploy --only functions,将函数部署到Firebase服务器。

4. Android端处理通知展示

自定义FirebaseMessagingService类,处理接收到的FCM消息并展示通知:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String CHANNEL_ID = "chat_notification_channel";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        
        // 构建通知
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(remoteMessage.getNotification().getTitle())
                .setContentText(remoteMessage.getNotification().getBody())
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true);

        // Android 8.0+ 创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "聊天通知",
                    NotificationManager.IMPORTANCE_HIGH);
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }

        // 展示通知
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify((int) System.currentTimeMillis(), builder.build());
    }

    // 令牌更新时重新存储
    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        saveTokenToRealtimeDb(token);
    }
}

在AndroidManifest.xml中注册该Service:

<service
    android:name=".MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

免费方案注意事项

  • Cloud Functions Spark计划每月提供100,000次免费调用,FCM每月提供1,000,000条免费消息,足够小型应用使用
  • 需确保Realtime Database规则允许Cloud Functions读取用户令牌和群组数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:25:19