使GCM在后台运行iOS设备

时间:2015-06-29 06:56:28

标签: ios push-notification apple-push-notifications google-cloud-messaging

我尝试将GCM用于IOS和Android客户端。当应用程序位于前台时,它似乎可以与IOS一起使用,但是,当应用程序在后台时,通知中心不会收到消息并且didReceiveRemoteNotification with completionHandler没有被调用。< / p>

我发现一个问题是从GCM到APNS的格式错误的消息。也就是说,它的外观如何:

[message: New message, collapse_key: do_not_collapse, from: **************]
虽然IOS推送通知应该在通知中有aps键,我是对的吗?以及内容可用设置为1.例如:

{     &#34; APS&#34; :{         &#34;内容可用&#34; :1     },     &#34;数据-ID&#34; :345 }

顺便说一句,在前台应用程序中接收消息,问题仅在于背景。关于如何处理问题,让GCM同时适用于ios和android的任何建议?

更新: 这就是我在网上发现的:

  

关于实际通信,只要应用程序在iOS设备上处于后台,GCM就会使用APNS发送消息,该应用程序的行为与使用Apple的通知系统类似。但是当应用程序处于活动状态时,GCM会直接与应用程序进行通信

所以我在前台模式收到的消息:

  

[消息:新消息,collapse_key:do_not_collapse,来自:**************]

来自GCM的直接消息(APNS根本没有参与此事)。所以问题是:APNS是否重新格式化GCM发送给它的内容以遵守ios通知格式?如果是这样,我怎么知道APNS实际上做了什么,是否它以不同的格式向我发送通知?有没有办法查看来自APNS的传入数据的日志?

更新 好的,我设法改变了消息的结构,现在在前台模式下,我收到以下消息:

  

收到通知:[&#34; aps&#34;:{&#34; alert&#34;:&#34;简单信息&#34;,&#34;内容可用&#34;:1}, collapse_key:do_not_collapse,from:**************]

现在它的格式似乎很好,但是当应用程序在后台时仍然没有反应。 didReceiveRemoteNotifification completionHandler没有被调用!我应该寻找什么,问题出在哪里?方括号是推送通知的问题吗?更准确地说,ios不会从收到的通知中发布任何警报/徽章/横幅。

5 个答案:

答案 0 :(得分:26)

每个可怜的灵魂都在寻求对GCM背景之谜的回答。我解决了它,问题出在格式上。我发布了正确的格式以及将Http请求发送到GCM所需的Java代码以及一些消息。 所以Http请求在头文件中应该有两个字段,即:

Authorization:key="here goes your GCM api key"
Content-Type:application/json for JSON data type

然后消息体应该是一个带有“to”和“notification”键的json字典。例如:

{
  "to": "gcm_token_of_the_device",
  "notification": {
    "sound": "default",
    "badge": "2",
    "title": "default",
    "body": "Test Push!"
  }
}

这是使用GCM将push发送到指定设备的简单java程序(仅使用java库):

public class SendMessage {

    //config
    static String apiKey = ""; // Put here your API key
    static String GCM_Token = ""; // put the GCM Token you want to send to here
    static String notification = "{\"sound\":\"default\",\"badge\":\"2\",\"title\":\"default\",\"body\":\"Test Push!\"}"; // put the message you want to send here
    static String messageToSend = "{\"to\":\"" + GCM_Token + "\",\"notification\":" + notification + "}"; // Construct the message.

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

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

            System.out.println(messageToSend);
            // Open connection
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

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

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

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

            byte[] data = messageToSend.getBytes("UTF-8");
            wr.write(data);

            //Send the request and close
            wr.flush();
            wr.close();

            //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();

            //Print result
            System.out.println(response.toString()); //this is a good place to check for errors using the codes in http://androidcommunitydocs.com/reference/com/google/android/gcm/server/Constants.html

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

答案 1 :(得分:23)

请务必注意,在iOS设备上,如果使用GCM的应用已被杀死(在应用切换器中刷过),那么只有在您发送带有“通知”的通知时,您的设备才会在收到消息时醒来,“ content_available“和”priority“(设置为”high“)。如果你有一个或另一个,它可能会在应用程序被杀死时起作用。但是一旦应用程序被杀死,你必须在通知负载中拥有所有这三个密钥。

这样的事情:

todoList

答案 2 :(得分:7)

根据此处的文档尝试在您的有效负载中设置优先级密钥:https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message

  • 正常优先级在APN术语中等于5
  • 高优先级在APN术语中等于10

此处您有关于Apple APN优先级及其行为的更多信息: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html

示例有效负载:

{
  "to": "gcm_device_token",
  "priority": "high",
  "content_available": false,
  "notification": {
    "sound": "default",
    "badge": "1",
    "title": "Push Title",
    "body": "Push Body"
  }
}

答案 3 :(得分:0)

  1. 这对C#来说,认为这可能会有所帮助。我也有这个问题 将content_available添加到true后,它可以正常工作。根据 Apple文档,这是操作系统理解存在的方式 应用在后台时的通知。

        JObject notification =new Object(
        new JProperty("to","put token which you get from running client application "),   
        new JProperty("content_available",true),
        new JProperty("priority","high"),
        new JProperty("notification",new JObject(
        new JProperty("title","message"),
        new JProperty("body","test message")
         ))
        );
    

答案 4 :(得分:0)

使用nodeJS和node-gcm npm库我发现以下有效负载适用于iOS,对于Android我发送略有不同的有效负载,因为我想拦截所有推送通知在将它们显示在系统托盘中之前:

{ dryRun: false,
  data: 
   { customKey1: 'CustomValue1',
     customKey2: 'CustomValue2',
     content_available: '1',
     priority: 'high' },
  notification: 
   { title: 'My Title',
     icon: 'ic_launcher',
     body: 'My Body',
     sound: 'default',
     badge: '2' } }

当然,您需要确保您的iOS应用可以处理入站通知,但这应该在您的应用处于后台时通知。