3

I'm trying to implement Firebase Topic Messaging in an Android application, and I'm attempting to build a HTTP post request, and I'm receiving a response code of 400. I have looked at various solutions but none of them have seemed to help.

Here is where I call the subclass of AsyncTask:

try{new FirebaseSendMessage().execute("Hello world");}
                catch (Exception e) {
                    Log.d("Exception", e.toString());
                }

Here is my Async Task class's subclass.

class FirebaseSendMessage  extends AsyncTask<String, Integer, Double> {
private final static String USER_AGENT = "Mozilla/5.0";
private final static String AUTH_KEY = "<My firebase authorization key obtained from firebase>";

private Exception exception;

protected Double doInBackground(String... params) {
    try {
        sendRequest(params);
    } catch (Exception e) {
        this.exception = e;
    }
    return null;
}

protected void onPostExecute(Long l) {
    // TODO: check this.exception
    // TODO: do something with the feed
}


public void sendRequest(String... params) {
    try {
        String urlString = "https://fcm.googleapis.com/fcm/send";
        URL url = new URL(urlString);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setDoOutput(true);
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setRequestProperty("Authorization", "key=" + AUTH_KEY);
        String postJsonData = "{\"to\": \"/topics/news\"\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}";
        con.setDoOutput(true);

        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(postJsonData);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("POST Response Code :: " + responseCode);

        if (responseCode == HttpURLConnection.HTTP_OK){
            System.out.println("succeeded");
        }
        /*InputStream is = con.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        //con.disconnect();*/
    }
    catch(IOException e){
        Log.d("exception thrown: ", e.toString());
    }
}

}

Error: I/System.out: POST Response Code :: 400

Please let me know if there are additional code snippets required to help me debug. Thanks in advance!

AL.
  • 36,815
  • 10
  • 142
  • 281
kmindspark
  • 487
  • 1
  • 7
  • 18
  • 2
    Please don't include this code in your Android application. You're exposing your `AUTH_KEY` to all users of your app, which means that it can (and will) be found by hackers who can then use it to send messages on your app's behalf. – Frank van Puffelen Jan 10 '17 at 04:05
  • It seems like firebase requires me to do it like this though. Is there a workaround? – kmindspark Jan 11 '17 at 04:46
  • 1
    You should use an app server. Or send notifications from the Firebase console. Embedding your server key in the client APK is *not* an alternative you should want. – Frank van Puffelen Jan 11 '17 at 05:11

2 Answers2

11

Error 400 means an Invalid JSON in your request:

Check that the JSON message is properly formatted and contains valid fields (for instance, making sure the right data type is passed in).

In your sendRequest, you missed a comma (,) between "news\" and \"data\" and a closing bracket (}):

String postJsonData = "{\"to\": \"/topics/news\"\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}";

which looks like this:

{"to": "/topics/news/""data":{"message":"...."}

Should be:

String postJsonData = "{\"to\": \"/topics/news\", \"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}}";

So that the JSON structure would be correct:

{"to": "/topics/news/",
 "data":{"message":"..."}
}
AL.
  • 36,815
  • 10
  • 142
  • 281
  • This is actually weird - we had the solution in production for months and now we're getting 400 errors ... still investigating – t1gor Oct 24 '18 at 12:49
-1

For those who are willing to use the authentication key in your application.

I suggest to encrypt the key manually by the SHA-1 of your application and the decrypt it at the time of runtime with the SHA-1 code.

  • that makes it just few minutes longer to get the key. you shouldn't be having it on the client app in the first place unless you want people messing up your application. user server or other firebase access methods. – Lassi Kinnunen Oct 19 '18 at 02:38