Android端Java代码从FCM Legacy API迁移至HTTP V1指南
迁移FCM Legacy API到HTTP V1版本的完整Java实现
前置步骤
- 登录Firebase控制台,进入项目设置 > 服务账号,生成并下载私钥JSON文件,将其放在项目资源目录下
- 确保项目依赖中包含以下库(以Gradle为例):
implementation 'com.google.auth:google-auth-library-oauth2-http:1.20.0' implementation 'com.squareup.okhttp3:okhttp:4.11.0' implementation 'org.json:json:20231013'
完整替换代码
下面是替换原有Legacy API代码的完整实现,包含令牌获取、通知构建和API调用:
import com.google.auth.oauth2.GoogleCredentials; import okhttp3.*; import org.json.JSONObject; import java.io.FileInputStream; import java.io.IOException; import java.util.Collections; import java.util.concurrent.TimeUnit; // 全局OkHttpClient实例,复用连接 private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); // 缓存OAuth2令牌,避免重复请求 private String cachedFcmToken; private long tokenExpiryTime; private void sendPushNotification(String notificationTitle, String hisFcmToken, String notificationBody, String myUserID, String notificationPhotoUrl, String hisUserID) { try { // 1. 构建FCM V1请求体 JSONObject message = new JSONObject(); JSONObject notification = new JSONObject(); JSONObject data = new JSONObject(); JSONObject androidConfig = new JSONObject(); JSONObject androidNotification = new JSONObject(); // 设置通知内容 notification.put("title", notificationTitle); notification.put("body", notificationBody); notification.put("image", notificationPhotoUrl); // 设置Android端高优先级(对应Legacy的priority:high) androidNotification.put("priority", "high"); androidConfig.put("notification", androidNotification); // 设置自定义数据 data.put("isNewUncheckedLikeNotification", "true"); data.put("likerUserID", myUserID); // 组装完整消息结构 message.put("token", hisFcmToken); // 替代Legacy的"to"字段 message.put("notification", notification); message.put("data", data); message.put("android", androidConfig); JSONObject requestBody = new JSONObject(); requestBody.put("message", message); // 2. 获取FCM V1授权令牌 String authToken = getFcmAuthToken(); if (authToken == null) { Log.d("PushNotification", "Failed to get FCM auth token"); return; } // 3. 调用FCM V1 API callV1Api(requestBody, authToken, hisUserID); } catch (Exception e) { Log.d("sendLikePushNotification", "Exception: " + e.getMessage()); } } private String getFcmAuthToken() throws IOException { // 检查令牌是否未过期 if (cachedFcmToken != null && System.currentTimeMillis() < tokenExpiryTime) { return cachedFcmToken; } // 从服务账号JSON文件加载凭据 GoogleCredentials credentials = GoogleCredentials.fromStream( new FileInputStream("path/to/your/service-account-key.json")) // 替换为你的JSON文件路径 .createScoped(Collections.singletonList("https://www.googleapis.com/auth/firebase.messaging")); credentials.refreshIfExpired(); String token = credentials.getAccessToken().getTokenValue(); // 缓存令牌,设置过期时间(提前5分钟刷新) tokenExpiryTime = System.currentTimeMillis() + (credentials.getAccessToken().getExpirationTime().getTime() - System.currentTimeMillis() - 300000); cachedFcmToken = token; return token; } private void callV1Api(JSONObject requestBody, String authToken, String hisUserID) { MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody body = RequestBody.create(requestBody.toString(), JSON); // 替换为你的Firebase项目ID String projectId = "your-firebase-project-id"; String url = "https://fcm.googleapis.com/v1/projects/" + projectId + "/messages:send"; Request request = new Request.Builder() .url(url) .post(body) .addHeader("Authorization", "Bearer " + authToken) .addHeader("Content-Type", "application/json") .build(); OK_HTTP_CLIENT.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.d("PushNotification", "Request failed: " + e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { Log.d("PushNotification", "Notification successfully sent to user: " + hisUserID); } else { String errorBody = response.body() != null ? response.body().string() : "No error details"; Log.d("PushNotification", "Failed to send notification: " + response.code() + " " + response.message() + " | Details: " + errorBody); } response.close(); } }); }
关键变化说明
- 请求URL:从
https://fcm.googleapis.com/fcm/send改为https://fcm.googleapis.com/v1/projects/{项目ID}/messages:send,需替换为你的实际项目ID - 授权方式:不再使用Legacy的服务器密钥,改为通过服务账号获取OAuth2令牌
- 消息结构:
- 目标令牌从
to字段改为token字段 - 高优先级设置需要放在
android.notification.priority下(iOS对应apns.payload.aps.priority) - 整体消息需要包裹在
message对象中
- 目标令牌从
- 令牌缓存:添加了令牌缓存逻辑,避免每次请求都重新获取,提升效率
注意事项
- 确保服务账号JSON文件的路径正确,且在打包时能被正确读取
- 令牌过期时间设置了提前5分钟刷新,避免令牌在请求过程中过期
- 错误处理中增加了错误体的读取,方便排查问题
内容的提问来源于stack exchange,提问作者Flower girl
相关产品推荐
相关产品推荐

