GCM推送通知不会传递给设备

时间:2016-03-09 21:11:58

标签: java android java-ee push-notification google-cloud-messaging

我们(Panos和Rainer - 请参阅评论)有一台服务器和几个Android设备。

我们希望通过GCM将推送通知从我们的服务器发送到Android设备。

现在我们向GCM服务器发出一个帖子请求。 GCM服务器的响应是一切都很好(成功== 1甚至是消息ID)! 但推送通知永远不会传递给设备。

如果我们使用相同的数据和Chrome插件邮递员,则会立即发送通知。

我们尝试了很多不同的解决方案。我们始终得到GCM服务器的反馈,一切正常 - 但推送通知不会发送。

我们也试过这个: https://github.com/googlesamples/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java

7 个答案:

答案 0 :(得分:0)

This是用于Postman请求的数据,该数据没有任何问题。 Rainer已经提到我们在Java方面尝试了几个实现,似乎我们始终能够与服务进行通信并接收到目前为止看似正确的响应:

{
    "multicast_id":7456542468425129822,
    "success":1,
    "failure":0,
    "canonical_ids":0,
    "results":
    [{
        "message_id":"0:1457548597263237%39c590d7f9fd7ecd"
    }]
} 

答案 1 :(得分:0)

不确定我是否在正确的轨道上,但您的意思是下游HTTP消息(纯文本)吗?

尝试将以下JSON发送到服务(来自Postman),这又产生了积极响应,但这次通知没有到达设备(只是为了清楚说明,此时设备上没有应用程序)积极倾听来电通知 - >首先,我们只是想确保它们通常会到达设备上):

{ 
   "data": 
   {
      "score": "5x1",
      "time": "15:10"
   },
   "to" : "SECRET-DEVICE-TOKEN"
}

答案 2 :(得分:0)

感谢你们所有人在这里提供帮助,但说实话,这个问题真的令人沮丧。与一个接口\服务进行通信似乎无法返回有用的响应,以防请求包含可能最终阻止GCM向设备发送推送通知的恶意内容,感觉就像是痛苦的屁股。如果邮差也会失败我会说好的,你不能这么愚蠢:-)

以下是我们已经使用的一些快速实现。

  1. 实施例

        try 
        {
           URL url = new URL(apiUrl);
           HttpsURLConnection conn = (HttpsURLConnection);//also tried HttpURLConnection
           url.openConnection();
           conn.setDoOutput(true);
           conn.setRequestMethod("POST");
           conn.setRequestProperty("Content-Type", "application/json");
           conn.setRequestProperty("Authorization", "key="+apiKey);
    
           conn.setDoOutput(true);
    
           String json = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
    
           OutputStream os = conn.getOutputStream();
           os.write(json.getBytes());
           os.flush();
       }
       catch(Exception exc)
       {
         System.out.println("Error while trying to send push notification: "+exc);
       }
    
  2. 实施例

    HttpClient httpClient = HttpClientBuilder.create().build(); 
    
    try 
    {
        HttpPost request = new HttpPost(apiUrl);
        StringEntity params =new StringEntity("{\"priority\":\"high\",\"notification\":{\title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}");
        request.addHeader("Content-Type", "application/json");
        request.addHeader("Authorization", "key="+apiKey);
        request.setEntity(params);
        HttpResponse response = httpClient.execute(request);
    
        // check response
        System.out.println(response.getStatusLine().toString());
    }catch (Exception exc) {
        System.out.println("Error while trying to send push notification: "+exc);
    } finally {
        httpClient.getConnectionManager().shutdown(); //Deprecated
    }
    
  3. 实施例

    try
    {
        String charset = "UTF-8"; 
        URLConnection connection = new URL(apiUrl).openConnection();
        connection.setDoOutput(true);
        connection.setRequestProperty("Accept-Charset", charset);
        connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
        connection.setRequestProperty("Authorization", "key="+apiKey);
    
        String param = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
        try (OutputStream output = connection.getOutputStream()) 
        {
            output.write(param.getBytes(charset));
        }
    
        InputStream response = connection.getInputStream();
    }
    catch(Exception exc)
    {
        System.out.println("Error while trying to send push notification: "+exc);
    }
    
  4. 实施例

    try 
    {
        // prepare JSON
        JSONObject jGcmData = new JSONObject();
        JSONObject jData = new JSONObject();
    
        jData.put("message", "{ \"data\": {\"score\": \"5x1\",\"time\": \"15:10\"},\"to\" : \""+deviceToken+"\"}");
    
        jGcmData.put("to", deviceToken);
    
        jGcmData.put("data", jData);
    
        // Create connection to send GCM Message request.
        URL url = new URL("https://android.googleapis.com/gcm/send");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Authorization", "key=" + apiKey);
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
    
        // Send GCM message content.
        OutputStream outputStream = conn.getOutputStream();
        outputStream.write(jGcmData.toString().getBytes());
    
        // Read GCM response.
        InputStream inputStream = conn.getInputStream();
        String resp = IOUtils.toString(inputStream);
        System.out.println(resp);
     } catch (IOException e) {
        System.out.println("Unable to send GCM message. "+e);
    }
    

答案 3 :(得分:0)

您也可以发布您使用的网址。有一个新的GCM enpoint,如下所示:

<强> https://gcm-http.googleapis.com/gcm/send

我还不确定是什么原因引起了你的问题。但以下是经过测试和运作的:

public class Main {

    public static void main(String[] args) {
    // write your code here

        try {

            String url = "https://gcm-http.googleapis.com/gcm/send";

            URL obj = new URL(url);
            HttpsURLConnectionImpl conn = (HttpsURLConnectionImpl) obj.openConnection();


            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);

            conn.setRequestMethod("POST");
            conn.setRequestProperty ("Authorization", "key=***");

            String title = "Short title";
            String body = "A body :D";
            String token = "****";
            String data =  "{ \"notification\": { \"title\": \"" + title +"\", \"body\": \"" + body + "\" }, \"to\" : \"" + token + "\", \"priority\" : \"high\" }";
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
            out.write(data);
            out.close();

            String text = getText(new InputStreamReader(conn.getInputStream()));
            System.out.println(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getText(InputStreamReader in) throws IOException {
        StringBuilder sb=new StringBuilder();
        BufferedReader br = new BufferedReader(in);
        String read;
        while((read=br.readLine()) != null) {
            sb.append(read);
        }
        br.close();
        return sb.toString();
    }
}

答案 4 :(得分:0)

迈克,以你的榜样,它也在我们这边工作。在将您的实现与我们的方面进行比较之后,我发现的唯一真正的区别就是使用过的URL! 不知何故,我们的Java实现中使用的URL是https://android.googleapis.com/gcm/send

似乎https://gcm-http.googleapis.com/gcm/send是正确的,顺便说一下也用于我们的邮递员测试。

但是为什么我们失败的测试中的URL仍然有效并返回响应!

答案 5 :(得分:0)

在json中将优先级设置为高可以解决我的问题。

'registration_ids' => $id,
'priority' => 'high',
'data' => $load

答案 6 :(得分:0)

对于我们的情况,客户端Android设备有间歇性的互联网连接问题,即网络丢失导致通知传递失败。我们使用以下JAVA GCM代码解决了可靠性问题:

gcmPayload.setTime_to_live(messageExpiryTime); //in seconds. Set notification message expiry to give user time to receive it in case they have intermittent internet connection, or phone was off
gcmPayload.setPriority("high");

和APNS代码:

ApnsService apnsService = APNS.newService().withCert(certificateStream, configurations.getApnPassword()).withProductionDestination().build();
PayloadBuilder payloadBuilder = APNS.newPayload();
...
payloadBuilder.instantDeliveryOrSilentNotification(); //same as content-available=true
String payload = payloadBuilder.build();

Integer now =  (int)(new Date().getTime()/1000);
//use EnhancedApnsNotification to set message expiry time
for(String deviceToken : deviceTokens) {
    EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID() /* Next ID */,
        now + messageExpiryTime /* Expiry time in seconds */,
        deviceToken /* Device Token */,
        payload);
        apnsService.push(notification);
}

另外,如果您的后端服务器时间与客户端移动应用时间不同,请记得考虑时区。