GCM 使用 content_available 向 iOS 推送通知(无法从非活动状态调用)

Posted

技术标签:

【中文标题】GCM 使用 content_available 向 iOS 推送通知(无法从非活动状态调用)【英文标题】:GCM push notification to iOS with content_available (not working to invoke from inactive state) 【发布时间】:2015-06-17 13:32:04 【问题描述】:

我正在开发基于 Java REST 的 Web 服务,我正在尝试通过 Google Cloud Messaging 将消息从 Java API 发送到 ios 设备。出于学习目的,我使用了适用于 iOS 的 google 示例代码,并且当应用程序在前台时我能够发送消息,但当应用程序在后台时它不起作用。我尝试了几种负责从后台调用应用程序的“content_available”标志的变体。当应用程序处于前台时,它运行良好。我正在尝试在应用处于后台时显示通知。

HttpClient client = new DefaultHttpClient();
HttpPost post = null;
try 
    post = new HttpPost("https://android.googleapis.com/gcm/send");
 catch (URISyntaxException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

String regisID="My_iOS_Registration_Id-GVnH1gEsJ";
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
List<NameValuePair> notificationData = new ArrayList<NameValuePair>(1);
notificationData.add(new BasicNameValuePair("title", "title"));
JSONObject obj=new JSONObject();
obj.put("title", "title");
obj.put("alert", "title");
obj.put("sound", "default");
obj.put("badge", "1");
nameValuePairs.add(new BasicNameValuePair("to", regisID));
nameValuePairs.add(new BasicNameValuePair("notification", obj.toString()));
nameValuePairs.add(new BasicNameValuePair("content_available", "true"));

post.setHeader("Authorization",
        "key=MyKey");
try 
    HttpEntity entity = new UrlEncodedFormEntity(nameValuePairs);
 catch (UnsupportedEncodingException e1) 
    // TODO Auto-generated catch block
    e1.printStackTrace();

try 
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
 catch (UnsupportedEncodingException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

HttpResponse response = null;
try 
    response = client.execute(post);
 catch (HttpException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();
 catch (IOException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

HttpEntity entity1 = response.getEntity();
try 
    System.out.println("Hi response is : " + EntityUtils.toString(entity1));
 catch (ParseException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();
 catch (IOException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

return response.getStatusLine().toString();

这是我用于接收通知的 iOS 应用程序委托代码,基本上是谷歌示例代码,添加了用于显示通知的代码

// [START ack_message_reception]
- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo 
  NSLog(@" foregraound one Notification received: %@", userInfo);
  // This works only if the app started the GCM service
  [[GCMService sharedInstance] appDidReceiveMessage:userInfo];
  // Handle the received message
  // [START_EXCLUDE]
  [[NSNotificationCenter defaultCenter] postNotificationName:_messageKey
                                                  object:nil
                                                userInfo:userInfo];
  // [END_EXCLUDE]


  UILocalNotification *notification = [[UILocalNotification alloc]init];
  notification.repeatInterval = NSDayCalendarUnit;
  [notification setAlertBody:@"Hello world"];
  [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]];
  [notification setTimeZone:[NSTimeZone  defaultTimeZone]];
  [application setScheduledLocalNotifications:[NSArray      arrayWithObject:notification]];


- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler 
  NSLog(@" backgroun one Notification received: %@", userInfo);
  // This works only if the app started the GCM service
  [[GCMService sharedInstance] appDidReceiveMessage:userInfo];
  // Handle the received message
  // Invoke the completion handler passing the appropriate         UIBackgroundFetchResult value
  // [START_EXCLUDE]
  [[NSNotificationCenter defaultCenter] postNotificationName:_messageKey
                                                  object:nil
                                                userInfo:userInfo];
  handler(UIBackgroundFetchResultNoData);
  // [END_EXCLUDE]

  UILocalNotification *notification = [[UILocalNotification alloc]init];
  notification.repeatInterval = NSDayCalendarUnit;
  [notification setAlertBody:@"Hello world"];
  [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]];
  [notification setTimeZone:[NSTimeZone  defaultTimeZone]];
  [application setScheduledLocalNotifications:[NSArray    arrayWithObject:notification]];

我尝试在通知中以 JSON 字符串的形式发送数据,其中包含“content_available”、“content-available”的各种变体,值变体为'1'trueTRUE。它似乎没有反映我的变化。我已经尝试将“声音”作为“默认”发送,因为我在一些应该影响的问题中发现。我也为android实现了这个,它就像一个魅力。基本上,根据我通过 gcm 文档和 APNS 文档获得的知识,它应该调用由“内容可用”决定的第二种方法,但它对我不起作用。

这里是带有 content_available 的 google 文档的链接。

https://developers.google.com/cloud-messaging/server-ref#downstream

https://developers.google.com/cloud-messaging/server#payload

要查看“content_available”的一部分,请搜索​​页面以获取有关它的信息。

【问题讨论】:

【参考方案1】:

我通过彻底参考文档解决了这个问题,我的新工作 java 代码如下所示。

JSONObject subobj = new JSONObject();
subobj.put("sound", "default");
subobj.put("badge", "12");
subobj.put("title", "default");

JSONObject obj = new JSONObject();
obj.put("to", regisID);
obj.put("notification", subobj);
obj.put("content_available", new Boolean(true));

post.setHeader("Authorization",
        "key=MyKey");

post.setHeader("Content-Type",
        "application/json");
try 
    HttpEntity entity = new UrlEncodedFormEntity(nameValuePairs);
 catch (UnsupportedEncodingException e1) 
    // TODO Auto-generated catch block
    e1.printStackTrace();

【讨论】:

以上是关于GCM 使用 content_available 向 iOS 推送通知(无法从非活动状态调用)的主要内容,如果未能解决你的问题,请参考以下文章

尽管 content_available = true,但没有在后台调用 didReceiveRemoteNotification

GCM 如何使用 GCM 和 3rd 方服务器注销设备

使用 3rd 方库和为同一应用程序单独 GCM 实现时 GCM 注册步骤冲突?

GCM 中使用上游消息传递的消息流程图

GCM 无法使用公司 Google 帐户

如何使用 GCM 通知同步