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

如何通过FCM Token向Android特定用户推送通知?

没问题,我来帮你梳理下怎么用存储的FCM Token给特定用户推送通知。核心是要借助Firebase Admin SDK来完成推送逻辑——出于安全和权限限制,客户端本身不能直接发起FCM推送请求,必须通过后端/服务器端操作。下面分步骤说明:

1. 准备Firebase Admin SDK(后端/服务器端)

首先需要在你的后端项目(比如Node.js、Java、Python等)中集成Firebase Admin SDK:

  • 前往Firebase控制台,进入「设置」→「服务账号」,点击「生成新的私钥」,下载JSON格式的密钥文件。
  • 以Node.js为例,初始化Admin SDK:
const admin = require('firebase-admin');
// 替换为你的密钥文件路径
const serviceAccount = require('./path/to/your-service-account-key.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  // 替换为你的实时数据库URL
  databaseURL: "https://your-project-name.firebaseio.com"
});
2. 从实时数据库获取目标用户的FCM Token

假设你要给特定username的用户推送通知,先从数据库中读取对应的Token:

// 示例:获取username为"alice"的用户Token
const db = admin.database();
const targetUserRef = db.ref(`users/alice`);

targetUserRef.once('value')
  .then(snapshot => {
    const userData = snapshot.val();
    const targetToken = userData?.token;
    
    if (targetToken) {
      // 获取到Token后,调用推送函数
      sendNotificationToToken(targetToken, "新消息提醒", "你有一条未读消息");
    } else {
      console.log("该用户未注册FCM Token");
    }
  })
  .catch(error => {
    console.error("读取用户数据失败:", error);
  });
3. 编写推送通知的核心函数

借助Admin SDK的messaging模块,向指定Token发送通知:

function sendNotificationToToken(token, title, body) {
  const message = {
    notification: {
      title: title,
      body: body
    },
    token: token
  };

  admin.messaging().send(message)
    .then(response => {
      console.log("通知发送成功:", response);
    })
    .catch(error => {
      console.error("通知发送失败:", error);
    });
}
4. 客户端(Android)的接收优化

你已经实现了MyFirebaseMessagingService,只需要完善onMessageReceived方法,调用已有的sendNotification函数展示通知即可。另外注意适配Android 12+的PendingIntent权限:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        // 提取推送的标题和内容
        if (remoteMessage.getNotification() != null) {
            String notificationTitle = remoteMessage.getNotification().getTitle();
            String notificationBody = remoteMessage.getNotification().getBody();
            // 调用通知展示函数
            sendNotification(notificationTitle, notificationBody);
        }
    }

    @Override
    public void onNewToken(String token) {
        Log.d(TAG, "Refreshed token: " + token);
        sendRegistrationToServer(token);
    }

    private void sendRegistrationToServer(String token) {
        // 你的Token存储逻辑(已实现)
    }

    // 优化后的通知展示方法,支持接收标题
    private void sendNotification(String title, String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        // Android 12+ 需使用FLAG_IMMUTABLE或FLAG_MUTABLE
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

        String channelId = getString(R.string.default_notification_channel_id);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_default)
                .setContentTitle(title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, "消息通知", NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
        }

        // 用时间戳作为通知ID,避免多条通知被覆盖
        notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build());
    }
}
关键注意事项
  • 安全原则:绝对不要在Android客户端中直接使用FCM推送API或暴露服务账号密钥,否则会导致密钥泄露、推送权限被滥用。
  • Token刷新:你已经在onNewToken中处理了Token更新存储,这部分做得很到位,确保数据库中的Token始终是最新的。
  • 数据库规则:确保实时数据库的规则允许后端服务账号读取用户的Token数据(比如设置"users": { ".read": "auth != null" },或针对服务账号配置更精细的权限)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:32:42