【问题标题】:Firebase v1 HTTP api does not support nested JSON objectsFirebase v1 HTTP api 不支持嵌套的 JSON 对象
【发布时间】:2019-10-23 12:46:17
【问题描述】:

现状

我们发送一个 POST 请求 Firebase legacy URL https://fcm.googleapis.com/fcm/send 将通知 JSON 有效负载传送到我们的 Android 应用程序。我们的通知负载是标准数据中的嵌套 JSON 对象。下面给出了来自 Postman 的示例有效负载

{
 "registration_ids": [
   "${registration_id}"],
   "priority":"HIGH", 
 "data": {
   "notification": {
     "title": "Notification Data Title From Postman",
     "body": "Notification Data Body From Postman",
     "imageurl": "https://d2x51gyc4ptf2q.cloudfront.net/content/uploads/2015/10/GettyImages-51205958-700x367.jpg"
   },
   "fcm_options": {
           "analytics_label": "postman"
     }
 }
}

请求头如下:

Content-Type: application/json; charset=utf-8`
Authorization: key={{server_key}}

在本例中,使用如下所示的数据对象中嵌套的 JSON 对象来成功构造通知。

"data": {
       "notification": {
         "title": "Notification Data Title From Postman",
         "body": "Notification Data Body From Postman",
         "imageurl": "https://d2x51gyc4ptf2q.cloudfront.net/content/uploads/2015/10/GettyImages-51205958-700x367.jpg"
       }
}

服务器密钥是从 Firebase 控制台的项目设置中获取的。此有效负载已成功传送到相应设备上的 Android 应用以创建通知。

问题

我们想迁移到Firebase v1 HTTP request APIs。我正在尝试使用 OAuth2 Tokens 进行身份验证并向 Android 设备发送通知。下面给出了我想通过 V1 api 发送的有效负载

{
  "message": {
    "token": "${token}",
    "data": {
      "notification": {
        "title": "Notification Data Title From v1 API",
        "body": "Notification Data Body From v1 API",
        "imageurl": "https://d2x51gyc4ptf2q.cloudfront.net/content/uploads/2015/10/GettyImages-51205958-700x367.jpg",
        "extra_key": "extra_value"
      }
    },
    "android": {
      "priority": "HIGH",
      "fcm_options": {
        "analytics_label": "Test_Command_line"
      }
    }
  }
}

当我们向 v1 HTTP API 发出 HTTP POST 请求时,我收到 400 错误并显示以下错误消息。

{
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"title\" at 'message.data[3].value': Cannot find field.\nInvalid JSON payload received. Unknown name \"body\" at 'message.data[3].value': Cannot find field.\nInvalid JSON payload received. Unknown name \"imageurl\" at 'message.data[3].value': Cannot find field.\nInvalid JSON payload received. Unknown name \"extra_key\" at 'message.data[3].value': Cannot find field.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "message.data[3].value",
            "description": "Invalid JSON payload received. Unknown name \"title\" at 'message.data[3].value': Cannot find field."
          },
          {
            "field": "message.data[3].value",
            "description": "Invalid JSON payload received. Unknown name \"body\" at 'message.data[3].value': Cannot find field."
          },
          {
            "field": "message.data[3].value",
            "description": "Invalid JSON payload received. Unknown name \"imageurl\" at 'message.data[3].value': Cannot find field."
          },
          {
            "field": "message.data[3].value",
            "description": "Invalid JSON payload received. Unknown name \"extra_key\" at 'message.data[3].value': Cannot find field."
          }
        ]
      }
    ]
  }
}

但是当数据负载没有嵌套时,如下所示

"data": {
    "title": "Title that is not nested",
    "body": "Body that is not nested",
    "imageurl": "https://timedotcom.files.wordpress.com/2016/08/margot-robbie-beer-shower.jpg",
}

然后我得到 200 OK 响应。响应正文如下

{
  "name": "projects/<project_id>/messages/<message_id>"
}

期望的行为

我希望能够使用 Firebase v1 HTTP API 将嵌套的 data 负载传递到我们的 Android 应用,以便可以呈现通知。鉴于我在发送嵌套有效负载时遇到错误,我该如何实现?这是我用来发出 HTTP 请求的程序。该程序使用 Google-API 客户端、FreeMarker、Firebase-Admin 和 OKHttp。

public class FCMMessaging {

    public static void main(String[] args) throws IOException, FirebaseMessagingException {

        // File was downloaded from Firebase console URL: https://console.firebase.google.com/project/<project-id>/settings/serviceaccounts/adminsdk
        try(InputStream is =
                FCMMessaging.class.getClassLoader().getResourceAsStream("firebase-admin-service-account.json");) {

            GoogleCredential googleCredential = GoogleCredential
                    .fromStream(is)
                    .createScoped(Collections.singletonList("https://www.googleapis.com/auth/firebase.messaging"));
            googleCredential.refreshToken();
            String bearerToken = googleCredential.getAccessToken();

            Configuration cfg = new Configuration();

            // Where do we load the notification payload templates from:
            cfg.setClassForTemplateLoading(FCMMessaging.class, "");

            // Some other recommended settings:
            cfg.setDefaultEncoding("UTF-8");
            cfg.setLocale(Locale.US);
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
            Map<String, Object> templateMap = new HashMap<>();
            templateMap.put("token",
                    "my-token-id");

            Template template = cfg.getTemplate("notification_payload.json");
            StringWriter stringWriter = new StringWriter();
            template.process(templateMap, stringWriter);
            RequestBody requestBody = RequestBody.create(stringWriter.toString(), MediaType.get("application/json; charset=utf-8"));
            Request request = new Request.Builder().url("https://fcm.googleapis.com/v1/projects/<project-id>/messages:send")
                    .addHeader("Authorization", "Bearer " + bearerToken).post(requestBody).build();

            OkHttpClient client = new OkHttpClient();
            try (Response response = client.newCall(request).execute()) {
                System.out.println(response.body().string());
            }
        } catch (TemplateException te) {
            te.printStackTrace();
        }
    }
}

【问题讨论】:

  • 这个运气好吗?我也面临同样的问题。
  • @DerrylThomas 对 JSON 有效负载进行字符串化,并发送一个键:值对。在 Firebase 消息处理程序中反序列化。
  • 谢谢!期间我也想到了这一点。我注意到设备上接收到的有效负载似乎与旧 API 完全相同,这使我得出结论,FCM 一直在内部进行字符串化。
  • 你也注意到了吗?或者您是否必须调整应用代码中的任何内容以响应从 HTTP V1 API 接收到的新负载?
  • 我不必更改我的 Android 代码库,但我的后端服务必须更新模板,并序列化 JSON 对象。

标签: android firebase firebase-cloud-messaging android-notifications


【解决方案1】:

我发送官方 Golang 库及其对象,如下所示:

{
 "data": {
   "age":"37",
   "elite":"1",
   "message":"test 4",
   "name":"Денис"},
 "notification":{
   "title":"У Вас 2 новых сообщения!",
   "body":"test 4"},
 "android":{
   "collapse_key":"1",
   "priority":"normal",
   "data":{
     "badge":"2",
     "sound":"1",
     "type":"1"}},
 "fcm_options":{
   "analytics_label":"1"},
 "token":"some_token"}

【讨论】:

    猜你喜欢
    • 2023-02-14
    • 2020-11-10
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 2021-06-17
    • 1970-01-01
    相关资源
    最近更新 更多