基于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
相关产品推荐
相关产品推荐

