Push Notifications doesn't always trigger methods in iOS7 - ios

I'm receiving notifications using this method:
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadComments" object:nil];
}
That trigger this method:
- (void) reloadComments:(NSNotification *)notification{
NSDictionary* dict = [notification.userInfo objectForKey:#"commentNotification"];
NSString* video_id = [[[dict objectForKey:#"aps"] objectForKey:#"custom"] objectForKey:#"data"];
NSData* cData = [video_id dataUsingEncoding:NSUTF8StringEncoding];
NSError *errorJson2;
NSMutableDictionary *response = [NSJSONSerialization JSONObjectWithData:cData options:kNilOptions error:&errorJson2];
int number = [[commentsDictionary objectForKey:[NSString stringWithFormat:#"%#", [response objectForKey:#"video_id"]]] intValue];
number += 1;
[commentsDictionary setObject:[NSNumber numberWithInt:number] forKey:[NSString stringWithFormat:#"%#", [response objectForKey:#"video_id"]]];
}
I'm parsing the result and incrementing the number. This works correctly when i launch the app, in my device, through XCode. If i send 5 push notifications the number is 5.
If i do the same procedure without launching the app through XCode, the number is not correctly incremented.
Anyone has any experience with this and can point me in the right direction?

I added the completionHandler below and it started working.
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[self parsePushNotifications:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
}

Related

How to resume couchbase lite iOS replication task on push notification

I'm trying to temporarily resume (un-suspend?) my replication tasks in couchbase lite iOS when my app receives a push notification. I've tried the following in my AppDelegate.m
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"notification-body => %#", notification);
NSMutableArray *toSuspend = [NSMutableArray array];
CBLManager *manager = [CBLManager sharedInstance];
for (NSString* name in [manager allDatabaseNames]) {
CBLDatabase* db = [manager databaseNamed:name error:nil];
NSArray* replications = [db allReplications];
for(CBLReplication* rep in replications) {
if(rep.suspended) {
[rep setSuspended: NO];
[toSuspend addObject: rep];
}
}
}
[RCTPushNotificationManager didReceiveRemoteNotification:notification];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"notification-complete => %#", notification);
for(CBLReplication* rep in toSuspend) {
[rep setSuspended: YES];
}
completionHandler(UIBackgroundFetchResultNewData);
});
}
But the list of replicators is always empty even though I have 2 running. What am I doing wrong?

iOS network connection on notification

The following code generally works but throws an SSL handshake failed (-9806) when the device is locked.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
NSString *roomID = [userInfo objectForKey:#"roomId"];
if (roomID) {
//tell firebase to update this conversation
[self.fb updateChatRoomMessages:roomID withBlock:^(BOOL success) {
/*code gets to here as I can see that with breakpoints,
but before we get here we can see the SSL handshake
error in console (only when phone is locked)*/
handler(UIBackgroundFetchResultNewData);
}];
} else {
handler(UIBackgroundFetchResultNoData);
}
}
Now basically updateChatRoomMessages tries to talk to firebase but I assume the problem is with just about any network connection. Is there known any restriction of the sort?
Any ideas?
Update - rest of the code
(void)updateChatRoomMessages:(NSString *)roomID withBlock:(void (^)(BOOL))completionBlock{
ChatRoomSummary *room = [[DataCollections shared] getChatRoomById:roomID];
Firebase *ref = [[Firebase alloc] initWithUrl:[NSString stringWithFormat:#"%#/chatdata/messages/%#",
self.baseURL, roomID]];
[ref observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *allMsgs) {
dispatch_async(dispatch_get_main_queue(), ^{
[room.messages removeAllObjects]; //clearing the list of messages so that we update it
NSDictionary *dict = allMsgs.value;
for(NSString *snapshot in [dict allKeys]) {
NSDictionary *currentSnapshot = [dict objectForKey:snapshot];
[currentSnapshot setValue:snapshot forKey:#"messageID"];
[[DataEventListener shared] onNewMessage:currentSnapshot forRoom:room preventNotification:YES];
}
[Utility notify:NOTIFY_NEW_ROOM];
[self updateBadges:nil];
if (completionBlock) {
completionBlock(YES);
}
});
}];
}

How to handle remote notifications when the app is not running

If my app is running on foreground or background this working fine. I am receiving the notifications and save it on the local database. But if the app killed from the background it receives the remote notifications but the following method is not called. And the issue is if I tap any one of the notification,only that notification will saved on the local database.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
[PFPush handlePush:userInfo];
NSLog(#"Received notification: %#", userInfo);
NSString *alertString = [[userInfo objectForKey:#"aps"]valueForKey:#"alert"];
NSLog(#"%#",alertString);
NSString *msgType = [userInfo objectForKey:#"messageType"];
NSString *senderId = [userInfo objectForKey:#"senderId"];
NSString *receverId = [userInfo objectForKey:#"receverId"];
NSString *msg = [userInfo objectForKey:#"message"];
NSString *timeStr = [userInfo objectForKey:#"Time"];
NSLog(#"msg type%# senderId %# receverId %# message %#",msgType,senderId,receverId,msg);
if ([AppDelegate isNetworkReachable]){
if ([msgType isEqualToString:#"CHAT"]) {
Chatmessage *Cmsg=[[Chatmessage alloc]init];
Cmsg.chat_date =timeStr;
Cmsg.chat_image =#"";
Cmsg.chat_message = msg;
Cmsg.chat_Receiver_Id = receverId;
Cmsg.chat_Sender_Id = senderId;
NSLog(#"recid%#",Cmsg.chat_Receiver_Id);
NSMutableArray *arryMsg = [[NSMutableArray alloc]init];
arryMsg = [[DBModelNew database]getChatMessageBasedOnTime:receverId SenId:senderId time_stamp:timeStr message:msg];
if (arryMsg.count == 0) {
[[DBModelNew database]insertmsg:Cmsg];
}
[[NSNotificationCenter defaultCenter]postNotificationName:#"receivedmessage" object:nil];
chatHistory *chatObj = [[chatHistory alloc]init];
chatObj.chat_meta_id = [NSString stringWithFormat:#"%#",senderId];
chatObj.last_send_message = msg;
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSString *str=[dateFormatter stringFromDate:[NSDate date]];
chatObj.last_time_stamp = [self dateformat:str];
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:senderId];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (NSDictionary *dict in objects) {
[[dict objectForKey:#"ProfilePic"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
if (image) {
chatObj.fndimage = image;
chatObj.name = [dict objectForKey:#"name"];
[[DBModelNew database]insertChat:chatObj];
[[NSNotificationCenter defaultCenter]postNotificationName:#"receivedNewMessage" object:nil];
}
}
}
}];
}
}
}];
}
}
}
From the Apple docs, if the user hard closes the app it does not call the method.
In addition, if you enabled the remote notifications background mode,
the system launches your app (or wakes it from the suspended state)
and puts it in the background state when a remote notification
arrives. However, the system does not automatically launch your app if
the user has force-quit it. In that situation, the user must relaunch
your app or restart the device before the system attempts to launch
your app automatically again.
If you want to launch specific payload dictionary from viewDidLoad then you simply call the following :
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
And you get the userInfo this way:
NSString *msgType = [localNotif objectForKey:#"messageType"];
And now you can act accordingly. This is just for the circumstances you stated in your title. When the app is not 'running' (terminated)

Why is Apple Watch not syncing with App delegate & NSUbiquitousValueStore?

I run this in my View Controller:
NSString *indexV = [NSString stringWithFormat:#"%d", index];
[[NSUbiquitousKeyValueStore defaultStore] setString:indexV forKey:#"index"];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
indexV = [[NSUbiquitousKeyValueStore defaultStore] stringForKey:#"index"];
NSLog(#"index V: %#", indexV);
Then quit the app.
In my AppDelegate I have:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
NSString *indexV = [[NSUbiquitousKeyValueStore defaultStore] stringForKey:#"index"];
NSLog(#"indexV: %#", indexV);
NSDictionary *d = #{#"index" : indexV};
reply(d);
In my InterfaceController I have:
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
[self sync];
- (void)sync {
[WKInterfaceController openParentApplication:#{#"give" : #"give"} reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"index: %#", replyInfo[#"index"]);
if (replyInfo[#"index"]) {
index = [replyInfo[#"index"] intValue];
In the iPhone app, I see the log where index is being set to an integer > 0.
Why is this string not synchronizing between apps?
I am able to send arrays ok.
Yes I have app groups configured, which is how - (void)application:(UIApplication *)application handleWatchKitExtensionRequest: .. will respond at all.
But when I run the Apple Watch app, index always comes through as #"0".

Push Notification works only once

The push notification only works when the app is in background ,But it didn't work when i removed it from background also when it returned to background , i didn't receive any push notifications. I had to delete the app and download it again from testflight to be able to receive push notifications.
here's the code
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
#if !TARGET_IPHONE_SIMULATOR
//Do stuff that you would do if the application was not active
NSLog(#"remote notification: %#",[userInfo description]);
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
NSLog(#"Aps Info : %#",apsInfo);
NSString *alert = [apsInfo objectForKey:#"alert"];
NSLog(#"Received Push Alert: %#", alert);
NSString *sound = [apsInfo objectForKey:#"sound"];
NSLog(#"Received Push Sound: %#", sound);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
NSString *badge = [apsInfo objectForKey:#"badge"];
NSLog(#"Received Push Badge: %#", badge);
application.applicationIconBadgeNumber = [[apsInfo objectForKey:#"badge"] integerValue];
#endif
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSInteger pushCode = [userInfo[#"pushCode"] integerValue];
NSLog(#"Silent Push Code Notification: %i", pushCode);
NSDictionary *aps = userInfo[#"aps"];
NSString *typeID = userInfo[#"type_id"];
NSString *alertMessage = aps[#"alert"];
NSLog(#"Type ID %#",typeID);
NSArray * array =[typeID componentsSeparatedByString:#","];
NSLog(#"Item %#,Item2 %#",[array objectAtIndex:0],[array objectAtIndex:1]);
[self typeID:[array objectAtIndex:0] userID:[array objectAtIndex:1] message:alertMessage];
NSLog(#"apss%#,alert%#,%#",aps,alertMessage,userInfo);
}
The problem is in the method:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
}
you should "catch" the notifications which arrive in background with this method:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
}
the fetchCompletionHandler method is designed for receiving "silent" push messages, which gets called prior to didReceiveRemoteNotification, if implemented.

Resources