Java 谷歌云消息:don';当iOS应用程序处于后台时,无法接收警报

Java 谷歌云消息:don';当iOS应用程序处于后台时,无法接收警报,java,ios,objective-c,google-cloud-messaging,Java,Ios,Objective C,Google Cloud Messaging,我遵循本教程在iOS应用程序上实现了GCM。我的应用服务器是一个用Java编写的google应用引擎,我使用gcm-server.jar库。我认为我的证书很好,我可以注册,获得令牌,甚至可以接收我的应用服务器发送的消息内容。但是,当应用程序处于后台时,我不会收到任何通知警报,我总是在单击应用程序图标重新启动时才会收到通知警报 我认为这是因为我只实现了didReceiveMemotentification:而不是didReceiveMemotentification:fetchCompletion

我遵循本教程在iOS应用程序上实现了GCM。我的应用服务器是一个用Java编写的google应用引擎,我使用gcm-server.jar库。我认为我的证书很好,我可以注册,获得令牌,甚至可以接收我的应用服务器发送的消息内容。但是,当应用程序处于后台时,我不会收到任何通知警报,我总是在单击应用程序图标重新启动时才会收到通知警报

我认为这是因为我只实现了
didReceiveMemotentification:
而不是
didReceiveMemotentification:fetchCompletionHandler:
,所以我实现了它而不是第一个,但在后台也没有收到通知,更糟糕的是,应用程序崩溃了,比如“发送到实例DidReceiveMemoteNotification的无法识别的选择器:”好像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
AppDelegate()
@属性(非原子,强)NSDictionary*注册选项;
@属性(非原子,强)GlgInstancedTokenHandler registrationHandler;
@结束
@实现AppDelegate
-(BOOL)应用程序:(UIApplication*)应用程序使用选项完成启动:(NSDictionary*)启动选项{
//--设置通知
[[GCMService sharedInstance]startWithConfig:[GCMConfig defaultConfig]];
if([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
NSLog(“案例iOS8”);
//iOS 8通知
[应用程序注册表通知设置:[UIUserNotificationSettings设置类型:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)类别:无];
[申请登记处证明];
}
其他的
{
NSLog(“案例iOS7”);
//iOS<8通知
[应用程序注册信息类型:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
self.registrationHandler=^(NSString*registrationToken,NSError*error){
如果(注册令牌!=nil){
NSUserDefaults*默认值=[NSUserDefaults standardUserDefaults];
[默认设置setObject:registrationToken-forKey:TOKENGCM];
NSLog(@“注册令牌:%@”,注册令牌);
//一些代码
}否则{
NSLog(@“注册到GCM失败,错误:%@”,错误。localizedDescription);
}
};
返回YES;
}
-(无效)应用程序将重新签名:(UIApplication*)应用程序{
}
-(无效)应用程序标识符背景:(UIApplication*)应用程序{
[[GCMService sharedInstance]断开连接];
}
-(无效)应用程序将进入前台:(UIApplication*)应用程序{
}
-(无效)应用IDBECOMEACTIVE:(UIApplication*)应用{
//连接到GCM服务器以接收非APNS通知
[[GCMService sharedInstance]connectWithHandler:^(N错误*错误){
如果(错误){
NSLog(@“无法连接到GCM:%@”,错误。localizedDescription);
}否则{
NSLog(@“连接到GCM”);
// ...
}
}];
}
-(无效)申请将终止:(UIApplication*)申请{
}
-(无效)申请:(UIApplication*)申请
DidRegisterForRemotonificationswithDeviceToken:(NSData*)deviceToken{
//使用默认配置启动InstanceID共享实例并请求注册
//用于启用通知接收的令牌
[[GlgInstanceId sharedInstance]startWithConfig:[GlgInstanceIdConfig defaultConfig]];
self.registrationOptions=@{kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:@NO};
[[GlgInstanceId sharedInstance]具有授权身份的令牌:发件人\u ID
经营范围:KGLINSTANCEIDSCOPEGCM
选项:自注册选项
处理程序:self.registrationHandler];
}
-(无效)应用程序:(UIApplication*)应用程序未能注册远程通知错误:(N错误*)错误{
NSLog(@“注册错误。错误:%@”,错误);
}
-(无效)刷新{
//注册令牌正在轮换,因此应用程序需要请求一个新令牌。
NSLog(@“GCM注册令牌需要更改”);
[[GlgInstanceId sharedInstance]具有授权身份的令牌:发件人\u ID
经营范围:KGLINSTANCEIDSCOPEGCM
选项:自注册选项
处理程序:self.registrationHandler];
}
-(无效)申请:(UIApplication*)申请
DidReceiveMemoteNotification:(NSDictionary*)用户信息{
NSLog(@“Notification received:%@”,userInfo);//如果应用程序位于前台,则在控制台中打印我的消息内容
UIApplicationState=[application applicationState];
如果(状态==UIApplicationStateActive){
NSString*cancelTitle=@“关闭”;
NSString*showTitle=@“显示”;
NSString*消息=[[userInfo valueForKey:@“aps”]valueForKey:@“警报”];
UIAlertView*alertView=[[UIAlertView alloc]initWithTitle:@“某些标题”
信息:信息
代表:赛尔夫
取消按钮:取消标题
其他按钮类型:showTitle,无];
[警报视图显示];
}
否则{
NSLog(@“非活动时收到的通知”);
[[UIApplication sharedApplication]设置应用程序徽章编号:99];
UIAlertView*BOOM=[[UIAlertView alloc]initWithTitle:@“BOOM”
消息:@“应用程序处于非活动状态”
代表:赛尔夫
取消按钮:@“啊哈!”
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;
}
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();
    }
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,
}
{
   "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",   
}