我认为这是因为我只实现了didReceiveRemoteNotification:而不是didReceiveRemoteNotification:fetchCompletionHandler:所以我实现了它而不是第一个但我在后台时没有收到通知,更糟糕的是,应用程序崩溃说“无法识别的选择器已发送”实例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://image.noelshack.com/fichiers/2015/34/1440193492-gcm1.png
http://image.noelshack.com/fichiers/2015/34/1440193502-gcm2.png
EDIT3:我现在从我的应用服务器发送的请求:
public static void sendGCMMessage(String tag,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(); }
解决方法
(在iOS上,使用此字段表示APNS有效内容中可用的内容.当发送通知或消息并将其设置为true时,将唤醒非活动客户端应用程序.在Android上,数据消息默认唤醒应用程序. Chrome目前不受支持.)
content_available与Apple的内容相对应,您可以在this Apple Push Notification Service documentation找到它.
此外,您应该使用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,}
The Java library只是一个示例,您可以添加其他字段.例如,在Message.java类中,您可以添加两个私有变量,一个是private final Boolean contentAvailable,另一个是private final< String,String>通知.
您可以通过执行curl -i -H“Content-Type:application / json”-H“Authorization:key = API_KEY”-X POST -d'{“to”:“REGISTRATION_TOKEN”,在终端中尝试HTTP请求notificaiton“:{”sound“:”default“,”badge“:”1“,”title“:”default“,”body“:”test“,”content_available“:true}’https:// android .googleapis.com / gcm / send,或者在Postman中试用.
编辑:
如果您的应用程序已终止,并且您希望在设备中显示推送通知,则可以在HTTP请求正文中设置high priority(请注意,将消息设置为高优先级会导致电池消耗与正常优先级消息相比更多) .
HTTP请求示例:
{ "to" : "REGISTRATION_TOKEN","priority" : "normal",}