我尝试将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不会从收到的通知中发布任何警报/徽章/横幅。
答案 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
此处您有关于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)
这对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应用可以处理入站通知,但这应该在您的应用处于后台时通知。