Java – Google cloud messaging: when IOS app is in the background, it will not receive alerts

I have followed this tutorial https://developers.google.com/cloud-messaging/ios/client Implement GCM on my IOS application My application server is a Google application engine written in Java. I use GCM server jar https://github.com/google/gcm Library I think my certificate is very good. I can register, obtain tokens and even receive the contents of messages sent by my application server However, when the application is in the background, I will not receive any notification alerts. I will only receive notifications when I click the application icon to restart

I think this is because I only implemented didreceiveremotenotification: not didreceiveremotenotification: fetchcompletionhandler: so I implemented it instead of the first one, but I didn't receive a notification in the background. What's worse, The application crashed and said "unrecognized selector sent" instance didreceiveremotenotification: "it's like an error in userinfo. I do allow background mode in Xcode. This is the code I use:

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,kGGLInstanceIDAPNSServerTypeSand@R_184_2419@Option:@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

Can someone find out that I didn't receive a notice when I wasn't at the front desk?

Edit: Java code for sending GCM messages on the server side:

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: screenshot of post request http://image.noelshack.com/fichiers/2015/34/1440193492-gcm1.png http://image.noelshack.com/fichiers/2015/34/1440193502-gcm2.png

Edit3: the request I now send from my application server:

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();
    }

Solution

Based on GCM documentation, you can_ Available is set to true

(on IOS, use this field to indicate the content available in APNs valid content. When sending a notification or message and setting it to true, it will wake up the inactive client application. On Android, data message wakes up the application by default. Chrome is not supported at present.)

content_ Available corresponds to Apple's content. You can find it in this Apple Push Notification Service documentation

In addition, you should use notification payload to send messages to IOS applications to display banners when the application is in the background

This is an example HTTP request:

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 is just an example. You can add other fields For example, in message In the Java class, you can add two private variables, one is private final Boolean contentavailable, and the other is private final < string, string > notification

You can try HTTP request notificaiton ": {" sound ":" default "," badge ":" 1 "," title ":" default "," body ":" test "," content_available ": true} ’https:// android . googleapis. COM / GCM / send, or try it in postman

Edit:

If your application has terminated and you want to display push notifications in the device, you can set high priority in the HTTP request body (note that setting messages to high priority will cause more battery consumption than normal priority messages)

HTTP request example:

{
   "to" : "REGISTRATION_TOKEN","priority" : "normal",}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>