如何使用Retrofit在Android设备间发送FCM通知?
解决Retrofit发送FCM通知的IllegalArgumentException问题
看起来你遇到的java.lang.IllegalArgumentException大概率是接口定义里的几个错误导致的,我帮你梳理下问题点并给出修正方案:
核心问题分析
- 混用@Field和@Body:Retrofit不允许在同一个接口方法里同时使用表单字段(
@Field)和请求体(@Body)。FCM的发送接口要求JSON格式的POST请求,所有参数都应该封装在请求体里,而不是拆分出来用@Field传递。 - Authorization头格式错误:你的Header里
Authorization : key=...的冒号后面多了个空格,正确格式应该是Authorization: key=...,这个空格可能导致认证失败或者请求格式不被FCM服务器识别。
修正后的代码实现
1. 修正ApiInterface定义
把@Field去掉,将to字段整合到请求体中:
public interface ApiInterface { @Headers("Authorization: key=AAAA4Ubio1Q:APA91bGWkw84b1XX2nnnOKn8MO25U2giLRXXXTUkXidojFluZk_qKXXXlS27oMZZV5goTQdwRtpdmvI1iAPRZZDNKz6c-mpU6nvHZJ-Jg9f1fQ5NdttftqUpqwAkObLEEX26VFDDbXN8") @POST("fcm/send") Call<ResponseBody> sendChatNotification(@Body RequestNotification requestNotification); }
2. 定义正确的请求体实体类
需要创建对应FCM JSON结构的实体类,包含to和notification字段:
// 外层请求体 public class RequestNotification { private String to; private NotificationContent notification; public RequestNotification(String to, NotificationContent notification) { this.to = to; this.notification = notification; } // 生成Getter和Setter方法,或者用Lombok的@Data注解简化 } // 通知内容实体 public class NotificationContent { private String title; private String body; public NotificationContent(String title, String body) { this.title = title; this.body = body; } // 生成Getter和Setter方法 }
3. 调用接口发送通知的示例
// 构建通知内容 NotificationContent content = new NotificationContent("新消息", "这是一条来自其他设备的FCM通知"); // 构建请求体,传入目标设备的FCM Token RequestNotification request = new RequestNotification("目标设备的FCM Token", content); // 初始化Retrofit并调用接口(假设你已经有Retrofit实例) ApiInterface apiService = RetrofitClient.getInstance().create(ApiInterface.class); Call<ResponseBody> call = apiService.sendChatNotification(request); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { // 通知发送成功,处理后续逻辑 Log.d("FCM", "通知发送成功"); } else { // 处理失败响应,比如打印错误信息 try { Log.e("FCM", "发送失败:" + response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 处理网络异常 Log.e("FCM", "网络请求失败:" + t.getMessage()); } });
额外注意事项
- Retrofit配置:确保你的Retrofit实例添加了JSON转换器,比如
GsonConverterFactory,否则无法将实体类序列化为JSON请求体:Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://fcm.googleapis.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); - 安全建议:不要在客户端硬编码FCM Server Key!这会有密钥泄露的风险,建议通过自己的后端服务器中转发送FCM通知,客户端只需要调用自己的后端接口即可。
- Token有效性:确保目标设备的FCM Token是最新且有效的,如果Token过期或无效,FCM服务器会返回对应的错误信息。
内容的提问来源于stack exchange,提问作者iamkdblue
相关产品推荐
相关产品推荐

