java – 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:而不是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, 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 documentation,您可以将content_available设置为true.

(在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",
    "notification" : {
     "sound" : "default",
     "badge" : "1",
     "title" : "default",
     "body"  : "Test",
   },
   "content_available" : true,
   "priority" : "normal",
 }

转载注明原文:java – Google Cloud Messaging:当iOS App处于后台时,不会收到警报 - 代码日志