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:未提供相关实现代码
问题原因定位
- 推送目标Token配置错误:代码中从Firebase数据库拉取
isServerToken=true的Token作为推送目标,这类Token是服务端身份标识,不是客户端设备的FCM注册Token,向无效Token推送消息时FCM会返回失败,success字段为0。 - Notification构造参数传反:自定义Notification类构造方法参数顺序为
(String body, String title),但调用时第一个参数传入了标题(厂商名)、第二个参数传入了内容(订单提示),参数顺序不符合FCM接口要求可能导致请求被拒绝。 - 实体类映射/解析异常:
- 未配置Retrofit的Gson转换器,返回的JSON无法正确解析为MyResponse对象,int类型字段默认值为0
- MyResponse实体类字段和FCM接口返回字段不匹配,或开启代码混淆后未添加实体类keep规则,字段被混淆导致解析失败
- BASE_URL配置错误,请求未发送到FCM官方接口
https://fcm.googleapis.com/,返回内容结构不匹配
- 权限/密钥错误:APIService中配置的FCM Legacy服务器密钥和当前Firebase项目不匹配,请求鉴权失败返回异常结构。
- 日志缺失:代码未打印具体错误详情,无法直接定位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
相关产品推荐
相关产品推荐

