服务器端 GCM 返回错误 400

Posted

技术标签:

【中文标题】服务器端 GCM 返回错误 400【英文标题】:Server side GCM returns error 400 【发布时间】:2015-05-20 14:08:21 【问题描述】:

我正在尝试实施 GCM。 我编写了一个测试代码来了解它是如何工作的,但我在响应中不断收到错误 400。

我正在用 Java (JDK 7) 编写代码。

我关注了this toturial 的主题。 我在那里修改了给定的代码,并将 ObjectMapper 的使用更改为 Gson。

这是我的数据对象代码:

public class Data 
   private ArrayList<String> registration_ids;

   public Data() 
      this.registration_ids = new ArrayList<String>();  
      this.registration_ids.add("APA91...");  // There is the real device registration id here.
   

*我在server reference 中看到,在HTTP 协议中,我可以仅使用registration_ids 发送消息。 (其他都是可选的)

这里是发送消息的代码:

public static void post(String apiKey, Data data)

    try

        // 1. URL
        URL url = new URL("https://android.googleapis.com/gcm/send");

        // 2. Open connection
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 3. Specify POST method
        conn.setRequestMethod("POST");

        // 4. Set the headers
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Authorization", "key=" + apiKey);

        conn.setDoOutput(true);

        // 5. Add JSON data into POST request body

        // 5.1 Convert object to JSON
        Gson gson = new Gson();
        Type type = new TypeToken<Data>() .getType();

        String json = gson.toJson(data, type);

        System.out.println(json);
        // The printed string is
        // "registration_ids":["APA91..."]
        // with the correct registration id of my device.


        // 5.2 Get connection output stream
        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());


        // 5.3 Copy Content "JSON" into
        wr.writeUTF(json);

        // 5.4 Send the request
        wr.flush();

        // 5.5 close
        wr.close();

        // 6. Get the response
        int responseCode = conn.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(conn.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) 
            response.append(inputLine);
        
        in.close();

        // 7. Print result
        System.out.println(response.toString());

     catch (MalformedURLException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
    

我知道错误 400 表示 json 问题,但我对要发送的数据尝试了许多变体,但都没有奏效(在这些测试中,我手动创建了字符串,没有使用 gson)。

这是我收到的错误消息:

java.io.IOException:服务器返回 HTTP 响应代码:400 用于 URL:https://android.googleapis.com/gcm/send 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:526) 在 sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1675) 在 sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1673) 在 java.security.AccessController.doPrivileged(本机方法) 在 sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1671) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1244) 在 sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) 在 POST2GCM.post(POST2GCM.java:64) 在 App.main(App.java:8) 原因:java.io.IOException:服务器返回 HTTP 响应代码:400 用于 URL:https://android.googleapis.com/gcm/send 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626) 在 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468) 在 sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338) 在 POST2GCM.post(POST2GCM.java:59) ... 1 更多

你能帮我解决这个问题吗? 非常感谢你, 尤瓦尔。

【问题讨论】:

您可以使用 Sender 和 Message 助手类。他们将为您完成所有 JSON 翻译和发送,因此您无需自己处理输出流。看到他们在行动here。 【参考方案1】:

问题出在 DataOutputStream.writeChars() 和 DataOutputStream.writeUTF() 中。

感谢@Koh给出的链接,我把post函数中的write命令改成了:

wr.write(json.getBytes("UTF-8"));

现在消息发送成功!

【讨论】:

以上是关于服务器端 GCM 返回错误 400的主要内容,如果未能解决你的问题,请参考以下文章

始终从GCM中的php(服务器端)获取无效注册

React本机推送通知,GCM服务器返回401

AFNetworking - SSL - 添加了 .cer 文件,但在服务器端出现 400 错误

客户端&服务器端&GCM

GCM(谷歌云推送)客户端服务器端开发全指南(服务器篇)

用于 asp.net 的 GCM 推送通知服务器端