I've a very strange problem, I implemented:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
For silent remote push notification. It works perfect when app is in background and connected to Xcode. When I unplug any iOS device and run the app, move to background and send remote notification, didReceiveRemoteNotification:fetchCompletionHandler
not being called.
My code below:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSInteger pushCode = [userInfo[@"pushCode"] integerValue]; NSLog(@"Silent Push Code Notification: %i", pushCode); NSDictionary *aps = userInfo[@"aps"]; NSString *alertMessage = aps[@"alert"]; if (pushCode == kPushCodeShowText) { UILocalNotification *localNotif = [[UILocalNotification alloc] init]; localNotif.fireDate = [NSDate date]; localNotif.timeZone = [NSTimeZone defaultTimeZone]; localNotif.alertBody = alertMessage; localNotif.alertAction = @"OK"; localNotif.soundName = @"sonar.aiff"; // localNotif.applicationIconBadgeNumber = 0; localNotif.userInfo = nil; [[UIApplication sharedApplication] presentLocalNotificationNow:localNotif]; UILocalNotification *clearNotification = [[UILocalNotification alloc] init]; clearNotification.fireDate = [NSDate date]; clearNotification.timeZone = [NSTimeZone defaultTimeZone]; clearNotification.applicationIconBadgeNumber = -1; [[UIApplication sharedApplication] presentLocalNotificationNow:clearNotification]; } else if (pushCode == kPushCodeLogOut) { [[MobileControlService sharedService] logoutUser]; [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode]; } else if (pushCode == kPushCodeSendLocation) { [[MobileControlService sharedService] saveLocation]; } else if (pushCode == kPushCodeMakeSound) { [[MobileControlHandler sharedInstance] playMobileControlAlertSound]; // [[MobileControlHandler sharedInstance] makeAlarm]; [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode]; } else if (pushCode == kPushCodeRecordAudio) { if ([MobileControlHandler sharedInstance].isRecordingNow) { [[MobileControlHandler sharedInstance] stopRecord]; } else { [[MobileControlHandler sharedInstance] startRecord]; } [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode]; } completionHandler(UIBackgroundFetchResultNewData); } - (void)saveLocation { bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:bgTask]; }]; char *hostname; struct hostent *hostinfo; hostname = "http://m.google.com"; hostinfo = gethostbyname(hostname); if (hostname == NULL) { NSLog(@"No internet connection (saveLocation)"); return; } if (self.locationManager.location.coordinate.latitude == 0.0 || self.locationManager.location.coordinate.longitude == 0.0) { NSLog(@"saveLocation - coordinates are 0.0."); return; } NSLog(@"saveLocation - trying to get location."); NSString *postBody = [NSString stringWithFormat:@"Lat=%@&Lon=%@&Date=%@&userID=%@&batteryLevel=%@&version=%@&accuracy=%@&address=%@", self.myInfo.lat, self.myInfo.lon, self.myInfo.date, self.myInfo.userID, self.myInfo.batteryLevel, self.myInfo.version, self.myInfo.accuracy, self.myInfo.address]; NSURL *completeURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/saveLocation", WEB_SERVICES_URL]]; NSData *body = [postBody dataUsingEncoding:NSUTF8StringEncoding]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:completeURL]; [request setHTTPMethod:@"POST"]; [request setValue:kAPP_PASSWORD_VALUE forHTTPHeaderField:kAPP_PASSWORD_KEY]; [request setHTTPBody:body]; [request setValue:[NSString stringWithFormat:@"%d", body.length] forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; if (__iOS_7_And_Heigher) { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"saveLocation Error: %@", error.localizedDescription); } else { NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"\n\nResponseXML(saveLocation):\n%@", responseXML); [self cloudAcknowledge_whoSend:kPushCodeSendLocation]; } }]; [dataTask resume]; } else { [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError) { NSLog(@"saveLocation Error: %@", connectionError.localizedDescription); } else { NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"\n\nResponseXML(saveLocation):\n%@", responseXML); [self cloudAcknowledge_whoSend:kPushCodeSendLocation]; } }]; } } - (void)startBackgroundTask { bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:bgTask]; }]; } - (void)endBackgroundTask { if (bgTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } }
And [self endBackgroundTask]
is at the end of cloudAcknowledge
function. Any idea what the hell is going on here?
EDIT:
Payload goes like this: { aps = { "content-available" = 1; }; pushCode = 12; }
Apple does not offer a way to handle a notification that arrives when your app is closed (i.e. when the user has fully quit the application or the OS had decided to kill it while it is in the background). If this happens, the only way to handle the notification is to wait until it is opened by the user.
One of the major features of web apps (both on desktop and mobile browsers) is the ability to send push notifications that are delivered even when the website is closed.
Add a new capability by clicking on + Capability. Add Push Notifications and Background Modes to your project. Under Background Modes, check Background fetch and Remote notifications. This will allow us to send notifications from our server (Firebase Cloud Messaging) to the user.
If you run your app now, press the first button to request notification permission, then press the second to add an actual notification. Now for the important part: once your notification has been added press Cmd+L in the simulator to lock the screen.
There could be number of things might have gone wrong, The first from my own experience. In order to make silent push notification work. Your payload has to be structured correctly,
{ "aps" : { "content-available" : 1 }, "data-id" : 345 }
Does your push message has content-available: 1
if not then iOS will not call the new delegate method.
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With