让GCM在后台运行iOS设备

我正在尝试为IOS和Android客户端使用GCM。 当应用程序处于前台时,它似乎可以正常工作,但是,当应用程序处于后台时,通知中心不会收到消息,并且didReceiveRemoteNotification with completionHandler不会被调用。

我将问题确定为从GCM到APNS的错误格式的消息。 也就是说,这就是它的样子:

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

而IOS推送通知在通知中应该有aps关键字,对吗? 以及内容可用设置为1.例如:

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

顺便说一下,前台应用程序收到消息,问题只是背景。 任何build议,我应该如何解决一个问题,使GCM工作的iOS和Android?

更新 :这是我在网上find的:

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

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

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

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

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

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

现在看起来格式不错,但是当应用程序在后台时还是没有反应。 didReceiveRemoteNotifification completionHandler不会被调用! 我应该看什么,问题在哪里? 方括号可以成为推送通知的问题吗? 更准确地说,ios不会发布任何警报/徽章/横幅从传入的通知。

每一个可怜的人都想知道为什么要回答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!" } } 

这里是简单的java程序(只使用java库),使用GCM发送推送到指定的设备:

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

请注意,在iOS设备上,如果使用GCM的应用程序已被杀死(在应用程序切换器中被刷新),则只有在收到“notification”,“content_available”和“优先级”(设置为“高”)。 如果你有一个或另一个,它可能工作时,应用程序已被杀害。 但是,一旦应用程序被杀死,你必须在你的通知有效载荷中拥有所有这些密钥。

像这样的东西:

 { "to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "notification": { "title": "test", "body": "my message" }, "priority": "high", "content_available": true } 

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

  • 在APN术语中正常优先级等于5
  • APNs术语中的高优先级等于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" } } 
  1. 这是否为C#,认为这可能是help.I也有这个问题后,添加content_available为true,它的工作。 根据苹果的文档,这就是操作系统了解应用程序在后台时有通知的方式。

      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") )) ); 

使用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应用程序能够处理入站通知,但是当你的应用程序在后台时,这应该会通过。