CURRENT SITUATION
We send a POST request Firebase legacy URL https://fcm.googleapis.com/fcm/send to deliver notification JSON payload to our Android application. Our notification payload is a nested JSON object within a standard data. Our sample payload from Postman is given below
{
"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"
}
}
}
The request headers are as follows:
Content-Type: application/json; charset=utf-8`
Authorization: key={{server_key}}
In this example, the nested JSON object within the data object as shown below is used to successfully construct the notification.
"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"
}
}
The server key is obtained from the Firebase console's project settings. This payload is successfully delivered to an Android app on an appropriate device to create a notification.
PROBLEM
We want to migrate to Firebase v1 HTTP request APIs. I am attempting to use OAuth2 Tokens to authenticate and deliver notifications to the Android device. The payload that I want to send through V1 api is given below
{
"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"
}
}
}
}
When we make a HTTP POST request to the v1 HTTP API, I get a 400 error with the following error message.
{
"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."
}
]
}
]
}
}
But when the data payload is not nested as given below
"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",
}
then I get a 200 OK response. The response body is given below
{
"name": "projects/<project_id>/messages/<message_id>"
}
DESIRED BEHAVIOUR
I want to be able to deliver nested data payloads using Firebase v1 HTTP API to our Android app so that the notifications can be rendered. How can I achieve that given that I am getting errors when I send nested payloads? This is the program that I have been using to make HTTP requests. The program uses Google-API clients, FreeMarker, Firebase-Admin, and 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();
}
}
}