
本文详细介绍如何在android应用中通过fcm(firebase cloud messaging)服务端api,向指定设备令牌(token)发送精准推送通知,涵盖http请求构建、依赖配置、线程安全处理及关键注意事项。
本文详细介绍如何在android应用中通过fcm(firebase cloud messaging)服务端api,向指定设备令牌(token)发送精准推送通知,涵盖http请求构建、依赖配置、线程安全处理及关键注意事项。
在Android开发中,若需从App内部(而非后端服务器)直接调用FCM HTTP v1 API向特定用户发送推送通知,需注意:Google官方强烈建议将FCM密钥(Server Key)保留在可信服务端,但开发调试或轻量级场景下,仍可临时在客户端集成调用逻辑。以下为安全、可用且符合现代Android实践的实现方案。
✅ 推荐实现:使用OkHttp异步发送FCM消息
相比已弃用的HttpClientBuilder(Android 9+默认禁用且无TLS 1.2支持),推荐使用 OkHttp —— 轻量、高效、默认启用现代TLS,并天然支持异步非阻塞调用:
1. 添加依赖(app/build.gradle)
implementation 'com.squareup.okhttp3:okhttp:4.12.0' // 注意:无需额外引入 grpc-okhttp 或 okio — OkHttp 4.x 已内置完整IO栈
2. 构建并发送FCM推送请求(Java示例)
private void sendFcmNotification(String targetToken, String apiKey) {
// ✅ 构造标准FCM v1兼容JSON payload(推荐使用"to" + "notification" 或 "data")
String jsonPayload = String.format(
"{\n" +
" \"to\": \"%s\",\n" +
" \"notification\": {\n" +
" \"title\": \"Hello from Android\",\n" +
" \"body\": \"This is a test push notification.\"\n" +
" },\n" +
" \"data\": {\n" +
" \"click_action\": \"FLUTTER_NOTIFICATION_CLICK\",\n" +
" \"custom_key\": \"custom_value\"\n" +
" }\n" +
"}",
targetToken
);
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(
jsonPayload,
MediaType.get("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url("https://fcm.googleapis.com/fcm/send")
.post(body)
.addHeader("Authorization", "key=" + apiKey) // ⚠️ Server Key(非Web API Key!)
.addHeader("Content-Type", "application/json")
.build();
// ✅ 异步执行,避免主线程阻塞
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("FCM_SEND", "Request failed", e);
runOnUiThread(() -> Toast.makeText(MainActivity.this, "推送失败: " + e.getMessage(), Toast.LENGTH_SHORT).show());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
String result = responseBody != null ? responseBody.string() : "";
int code = response.code();
Log.d("FCM_SEND", "Response Code: " + code + ", Body: " + result);
runOnUiThread(() -> {
if (code == 200) {
Toast.makeText(MainActivity.this, "推送成功!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "推送失败,状态码:" + code, Toast.LENGTH_LONG).show();
}
});
}
}
});
}⚠️ 关键注意事项
-
密钥安全:key=
中的 API_KEY 必须是 Firebase Console → Project Settings → Cloud Messaging → Server key(⚠️ 不是Web Push证书密钥或App ID)。切勿硬编码或提交至Git,生产环境务必迁移至后端服务。 - Token有效性:确保 targetToken 是当前设备有效的FCM注册令牌(可通过 FirebaseMessaging.getInstance().getToken() 获取并持久化);过期/无效token将返回 mismatchSenderId 或 InvalidRegistration 错误。
-
消息类型选择:
- notification 字段由系统自动处理(前台/后台均显示通知栏),适合用户可见提醒;
- data 字段始终传递至客户端(即使App被杀),需自行处理展示逻辑,适合静默数据同步;
- 混合使用二者可兼顾体验与控制力。
- Android 12+ 适配:需在 AndroidManifest.xml 中声明 FOREGROUND_SERVICE 权限(若在前台服务中调用),但本例为普通Activity内调用,无需额外权限。
- 错误排查:常见响应码包括 401 Unauthorized(密钥错误)、400 Bad Request(JSON格式错误)、404 NotRegistered(token已失效)——建议解析响应体中的 "error" 字段获取具体原因。
✅ 总结
本文提供了一套稳定、可维护的Android端FCM推送调用方案:基于OkHttp异步通信,结构清晰、日志完备、线程安全。尽管客户端直连FCM存在安全风险,但在原型验证、内部测试或IoT类轻量应用中仍具实用价值。长期演进方向应是解耦至独立后端服务(如Cloud Functions、Node.js API),由其统一管理密钥、设备映射与消息路由逻辑。

















