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

Android FCM推送接口返回success=0而非预期1问题排查

问题场景

在Android端实现订单消息推送功能时,接收FCM推送接口响应出现异常,response.body().success字段返回值为0,不符合预期返回值1,界面弹出“Failed !!!”的Toast提示,代表推送请求未执行成功,相关业务实现代码如下:

mService = Common.getFCMService();
private void sendNotificationOrder(String order_number) {
    DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens");
    Query data = tokens.orderByChild("isServerToken").equalTo(true);
    data.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot postSnapShot:dataSnapshot.getChildren()) {
                Token serverToken = postSnapShot.getValue(Token.class);
                Notification notification = new Notification("Ziead's Company", "You have New Order" + order_number);
                Sender content = new Sender(serverToken.getToken(), notification);
                mService.sendNotification(content)
                        .enqueue(new Callback<MyResponse>() {
                            @Override
                            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
                                try {
                                       //Here It is Returning "0" not 1                                        
                                       System.out.println(response.body().success);
                                        if (response.code() == 200) {
                                            if (response.body().success == 1) {
                                                System.out.println("Succeedd");
                                                Toast.makeText(Cart.this, "Thank you , Order Place", Toast.LENGTH_SHORT).show();
                                                finish();
                                            } else {
                                                Toast.makeText(Cart.this, "Failed !!!", Toast.LENGTH_SHORT).show();
                                            }
                                        }
                                    }
                                    catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                                @Override
                                public void onFailure(Call<MyResponse> call, Throwable t) {
                                Log.e("ERROR", t.getMessage());

                            }
                        });

            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}

关联代码文件

  • Token.java
public class Token {
    private String token;
    private boolean isServerToken;

    public Token() {
    }

    public Token(String token, boolean isServerToken)
    {
        this.token = token;
        this.isServerToken = isServerToken;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public boolean isServerToken() {
        return isServerToken;
    }

    public void setServerToken(boolean serverToken) {
        isServerToken = serverToken;
    }
}
  • Notification.java
public class Notification {
    public String body;
    public String title;

    public Notification(String body, String title) {
        this.body = body;
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
  • Sender.java
public class Sender {
    public String to;
    public  Notification notification;

    public Sender(String to, Notification notification) {
        this.to = to;
        this.notification = notification;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public Notification getNotification() {
        return notification;
    }

    public void setNotification(Notification notification) {
        this.notification = notification;
    }
}
  • Common.java
public class Common {
    public static APIService getFCMService(){
        return RetrofitClient.getClient(BASE_URL).create(APIService.class);
    }
}
  • APIService接口
public interface APIService {
    @Headers(
            {
                    "Content-Type:application/json",
                    "Authorization:key=AAAA0EXeo9E:APA91bGeAWN69zVVIKh9ib_XA6OkMnEA1S0_sZILrJ1civQVF-eelOAF4o3qCOTZpRgSwb9bySoU92ypchs5BqOE2P1Y_FPlvUanIrV2g7RPCY7IpGjYqSK1rlKVxODm6v8R"
            }
    )
    @POST("fcm/send")
    Call<MyResponse> sendNotification(@Body Sender body);
}
  • RetrofitClient.java:未提供相关实现代码
问题原因定位
  1. 推送目标Token配置错误:代码中从Firebase数据库拉取isServerToken=true的Token作为推送目标,这类Token是服务端身份标识,不是客户端设备的FCM注册Token,向无效Token推送消息时FCM会返回失败,success字段为0。
  2. Notification构造参数传反:自定义Notification类构造方法参数顺序为(String body, String title),但调用时第一个参数传入了标题(厂商名)、第二个参数传入了内容(订单提示),参数顺序不符合FCM接口要求可能导致请求被拒绝。
  3. 实体类映射/解析异常:
    • 未配置Retrofit的Gson转换器,返回的JSON无法正确解析为MyResponse对象,int类型字段默认值为0
    • MyResponse实体类字段和FCM接口返回字段不匹配,或开启代码混淆后未添加实体类keep规则,字段被混淆导致解析失败
    • BASE_URL配置错误,请求未发送到FCM官方接口https://fcm.googleapis.com/,返回内容结构不匹配
  4. 权限/密钥错误:APIService中配置的FCM Legacy服务器密钥和当前Firebase项目不匹配,请求鉴权失败返回异常结构。
  5. 日志缺失:代码未打印具体错误详情,无法直接定位FCM返回的失败原因(如Token过期、参数非法等)。
修复方案
  • 修正推送目标逻辑:订单通知需要推送到下单用户的客户端设备,需将to字段替换为当前下单用户对应的客户端FCM注册Token,不要使用标记为isServerToken的服务端Token。
  • 修正Notification参数顺序,调整为内容在前、标题在后:
// 原错误写法:new Notification("Ziead's Company", "You have New Order" + order_number)
Notification notification = new Notification("You have New Order " + order_number, "Ziead's Company");
  • 补全Retrofit配置,确保添加Gson转换器,正确的RetrofitClient实现参考:
public class RetrofitClient {
    private static Retrofit retrofit = null;
    public static Retrofit getClient(String baseUrl) {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create()) // 必须添加Gson转换器,否则无法自动解析JSON响应
                    .build();
        }
        return retrofit;
    }
}

同时确认BASE_URL配置为FCM官方地址:https://fcm.googleapis.com/

  • 补全MyResponse实体类,和FCM返回结构完全匹配,增加错误字段方便排查:
import java.util.List;

public class MyResponse {
    public long multicast_id;
    public int success;
    public int failure;
    public int canonical_ids;
    public List<Result> results;

    public static class Result {
        public String message_id;
        public String error; // 存储具体失败原因,如InvalidRegistration、NotRegistered、MismatchSenderId等
    }
}
  • 添加混淆规则,避免实体类被R8/ProGuard混淆导致解析失败,在模块的proguard-rules.pro文件中添加:
# 替换为你项目中实体类所在的实际包路径
-keep class com.xxx.xxx.entity.** { *; }
  • 校验FCM密钥:进入Firebase控制台对应项目的「项目设置-云消息传递」页面,确认Legacy服务器密钥和APIService中Authorization头携带的key完全一致,无多余空格或拼写错误。
  • 完善错误日志打印逻辑,替换原有onResponse中的判断代码,方便快速定位问题:
@Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
    try {
        if (response.code() == 200) {
            MyResponse body = response.body();
            if (body != null && body.success == 1) {
                Toast.makeText(Cart.this, "Thank you , Order Place", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                // 打印具体失败原因
                if (body != null && body.results != null && !body.results.isEmpty()) {
                    Log.e("FCM_PUSH_ERROR", "Push failed reason: " + body.results.get(0).error);
                }
                Toast.makeText(Cart.this, "Failed !!!", Toast.LENGTH_SHORT).show();
            }
        } else {
            // 打印HTTP错误信息
            String errorBody = response.errorBody() != null ? response.errorBody().string() : "empty error body";
            Log.e("FCM_PUSH_ERROR", "Request error, code: " + response.code() + ", msg: " + errorBody);
            Toast.makeText(Cart.this, "Failed !!!", Toast.LENGTH_SHORT).show();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:07:04