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

使用FCM批量推送通知异常:仅能推送给首个设备的问题求助

问题解决步骤

1. 修复Android端Activity的推送逻辑

你当前在循环中每添加一个Token就调用一次推送接口,导致每次请求的Token列表是累加状态(如[token1]→[token1,token2]),还会重复发起无效请求。正确做法是先收集全所有Token,再统一调用接口:

binding.btnSend.setOnClickListener(v -> {
    db.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            List<String> tokens = new ArrayList<>();
            // 先一次性收集所有设备Token
            for (DataSnapshot dataSnapshot: snapshot.getChildren()){
                User_Model userModel = dataSnapshot.getValue(User_Model.class);
                tokens.add(userModel.getToken());
            }
            // 收集完成后再发起推送请求
            if (!tokens.isEmpty()) {
                API api = retrofit.create(API.class);
                Call<ResponseBody> call = api.sendNotification(
                    tokens,
                    binding.etNotificationTitle.getText().toString(),
                    binding.etNotificationBody.getText().toString()
                );
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        // 可添加推送发起成功的提示逻辑
                    }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        // 处理请求失败场景
                    }
                });
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Toast.makeText(AddNotificationActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
});

2. 修复Cloud Function的FCM请求格式

你的后端当前把传入的Token列表直接赋值给message.token,但FCM批量推送需要使用**tokens数组字段**,且消息结构要符合多播格式。修改index.js中的请求部分:

router.post('/send', function(req, res){
    getAccessToken().then(function(access_token){
        var title = req.body.title; 
        var body = req.body.body; 
        var tokens = req.body.token; // 对应前端传入的Token数组

        // 构建FCM多播消息结构
        const message = {
            notification: {
                body: body,
                title: title,
            },
            tokens: tokens // 替换原单个token字段为tokens数组
        };

        request.post({
            headers:{
                Authorization: 'Bearer '+access_token,
                'Content-Type': 'application/json' // 明确指定JSON类型请求头
            }, 
            url: "https://fcm.googleapis.com/v1/projects/你的项目ID/messages:send", // 替换为你的FCM v1接口地址
            body: JSON.stringify({ message: message })
        }, function(error, response, body){
            res.end(body);
            console.log(body);
        });
    });
});

3. 关键注意事项

  • 批量推送限制:FCM一次最多支持推送500个设备Token,若你的Token数量超过500,需要在后端将列表拆分为多个500以内的批次分别发送。
  • 请求头校验:必须添加Content-Type: application/json,否则FCM无法正确解析请求体。
  • 结果排查:FCM批量推送会返回每个Token的推送状态,可在后端解析返回的responses数组,记录失败的Token以便后续排查。

4. 可选优化:推送结果解析

在后端添加结果解析逻辑,方便定位推送失败的设备:

// 在request的回调函数中添加
function(error, response, body){
    if (!error && response.statusCode === 200) {
        const result = JSON.parse(body);
        result.responses.forEach((resp, index) => {
            if (resp.success) {
                console.log(`Token ${tokens[index]} 推送成功`);
            } else {
                console.log(`Token ${tokens[index]} 推送失败: ${resp.error.message}`);
            }
        });
    }
    res.end(body);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 06:27:55