使GCM在后台运行iOS设备

Ole*_*rov 26 push-notification apple-push-notifications ios google-cloud-messaging

我正在尝试将GCM用于IOS和Android客户端.当应用程序位于前台时,它似乎与IOS一起正常工作,但是,当应用程序在后台时,通知中心不会收到消息而didReceiveRemoteNotification with completionHandler不会被调用.

我发现一个问题是从GCM到APNS的格式错误的消息.也就是说,它看起来如何:

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

{"aps":{"content-available":1},"data-id":345}

顺便说一句,在前台应用程序中接收消息,问题仅在于背景.关于我应该如何解决问题,使GCM同时适用于ios和android的任何建议?

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

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

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

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

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

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

收到通知:["aps":{"alert":"Simple message","content-available":1},collapse_key:do_not_collapse,from:**************]

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

Ole*_*rov 26

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

Authorization:key="here goes your GCM api key"
Content-Type:application/json for JSON data type
Run Code Online (Sandbox Code Playgroud)

那么消息体应该是一个带有"to"和"notification"键的json字典.例如:

{
  "to": "gcm_token_of_the_device",
  "notification": {
    "sound": "default",
    "badge": "2",
    "title": "default",
    "body": "Test Push!"
  }
}
Run Code Online (Sandbox Code Playgroud)

这是使用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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你应该把它放在http请求体中.在此特定示例中,只需添加\"content_available \":\"1 \"作为messageToSend字符串的键. (3认同)
  • 谢谢.Google文档中没有任何迹象表明您需要使用"通知"键才能使用它.我们试图使用"数据"并在设备上得不到任何东西,尽管GCM会告诉我们已成功发送通知. (3认同)
  • 数据有效负载和通知有效负载均适用于iOS和Android.在iOS上,不同之处在于通过APNS发送通知有效负载,而数据有效负载通过GCM自己的连接发送,该连接仅在应用程序位于前台时才会发送.那么,如果我想在android和ios中使用GCM,有效负载应该只包含通知?或者数据和通知都没问题? (2认同)

小智 24

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

像这样的东西:

{
    "to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification": {
        "title": "test",
        "body": "my message"
    },
    "priority": "high",
    "content_available": true
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*sta 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"
  }
}
Run Code Online (Sandbox Code Playgroud)