get messages when user is offline in ios at quickblox - ios

I am using chat api for IOS of quickblox in my project, chat application, now everything is ok... When the user is online, or the application not removed from background he is getting push notifications and messages in chat page.. but when the application is removed from background, he is getting push notifications, but the message doesnt appear in the chat page it's appear only in the push notification... I sent my problem to quickblox support, they gave me a code to replace in my project, now my problem code is here:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
// Override point for customization after application launch.
cManager = [ConnectionManager sharedMannager];
[cManager sendNetworkIdUpdate:[[DataManager sharedCenter]currentnetworkIdentifier]];
[QBSettings setApplicationID:-----];
[QBSettings setAuthorizationKey:#"--------"];
[QBSettings setAuthorizationSecret:#"--------"];
[QBSettings setAccountKey:#"--------"];
[cManager getBlockedList];
if (launchOptions != nil) {
NSLog(#"Launched from push notification");
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSLog(#"%#",launchOptions);
[[DataManager sharedCenter]setPushData:[notification valueForKeyPath:#"aps.user_info"]];
// Do something with the notification dictionary
}
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application{
if ([[[DataManager sharedCenter]currentUser]userChatId]){
[QBUsers logOutWithDelegate:[ChatService instance]];
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
if ([[DataManager sharedCenter]chat_user] != nil) {
[[QBChat instance] loginWithUser:[[DataManager sharedCenter]chat_user]];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
BOOL isLoggedIntoChat = [[QBChat instance] isLoggedIn];
if (isLoggedIntoChat) {
[[QBChat instance] logout];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application{
if ([[UIApplication sharedApplication]applicationIconBadgeNumber]>0){
[UIApplication sharedApplication].applicationIconBadgeNumber=0;
[cManager clearBadge];
}
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
/*if ([[[DataManager sharedCenter]currentUser]userChatId]){
[QBUsers logOutWithDelegate:[ChatService instance]];
}*/
if ([[LocalStorageService shared]messagesHistory] && [[[DataManager sharedCenter]currentUser]userId]){
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[[LocalStorageService shared]messagesHistory]];
[[[DataManager sharedCenter]defaults]setObject:data forKey:[NSString stringWithFormat:#"%#%#",[[[DataManager sharedCenter]currentUser]userId],kMessageHistoryBlock]];
[[[DataManager sharedCenter]defaults]synchronize];
}
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSString* devToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"Update Token: %#",devToken);
[cManager sendPushTokenUpdate:devToken];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(#"Opend from push notification");
NSLog(#"%#",userInfo);
UIApplicationState state = [[UIApplication sharedApplication]applicationState];
if (state != UIApplicationStateActive){
if ([userInfo valueForKeyPath:#"aps.user_info"]){
[[DataManager sharedCenter]setPushData:[userInfo valueForKeyPath:#"aps.user_info"]];
[[NSNotificationCenter defaultCenter]postNotificationName:kShowPush object:nil];
}
}
[[NSNotificationCenter defaultCenter]postNotificationName:kUpdateTables object:nil];
[cManager clearBadge];
}
and the problem is still appearing ! , any help please ?

You have to do proper Chat logout. Server should know for sure that your user is offline
First of all, refer to the Chat in background mode documentation http://quickblox.com/developers/SimpleSample-chat_users-ios#Chat_in_background_mode
Try to do chat logout in applicationWillTerminate and applicationDidEnterBackground:
- (void)applicationWillTerminate:(UIApplication *)application
{
[[QBChat instance] logout];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[QBChat instance] logout];
}

Related

iOS, force quit app first, after tapping the receiving notification banner, app launch failed

I use APNs to send the notifications to my app. But my app does not work well when I did the following steps:
steps
swipe the app to force quit (app is not running, not in background mode ..)
send the notification from APNs
got the notification on my iPhone and I tapped the notification banner
app seemed to try to launch(showed the launch image), but launched fail (crash?)
my app can receive notification foreground and background.
Tap the notification banner in background then it can bring app to foreground then go to the view I wrote, everything works fine.
Except force quit the APP
here is my code in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController:[self navigationController]
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
UIMutableUserNotificationAction *acceptAction =
[[UIMutableUserNotificationAction alloc] init];
// Define an ID string to be passed back to your app when you handle the action
acceptAction.identifier = #"MARK_AS_READ_IDENTIFIER";
// Localized string displayed in the action button
acceptAction.title = NSLocalizedString(#"Mark as Read", nil);
// If you need to show UI, choose foreground
acceptAction.activationMode = UIUserNotificationActivationModeBackground;
// Destructive actions display in red
acceptAction.destructive = NO;
// Set whether the action requires the user to authenticate
acceptAction.authenticationRequired = NO;
// First create the category
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
// Identifier to include in your push payload and local notification
inviteCategory.identifier = #"actionCategory";
// Add the actions to the category and set the action context
[inviteCategory setActions:#[acceptAction]
forContext:UIUserNotificationActionContextDefault];
// Set the actions to present in a minimal context
[inviteCategory setActions:#[acceptAction]
forContext:UIUserNotificationActionContextMinimal];
NSSet *categories = [NSSet setWithObject:inviteCategory];
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert) categories:categories]];
// for calling didReceiveRemoteNotification when app first launch
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
[self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];
}
return YES;
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"Device token: %#",deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Fail to get device token: %#", error);
}
// tap the backgraund banner button
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)newUserInfo completionHandler:(void (^)())completionHandler {
if ([identifier isEqualToString:#"MARK_AS_READ_IDENTIFIER"]) {
// when tapping the background banner's button will mark the notification status to read
[Functions updateComingNotificationToRead];
}
if (completionHandler) {
completionHandler();
}
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)newUserInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
//NSLog(#"Notification received: %# %#", newUserInfo,[newUserInfo objectForKey:#"aps"] );
userInfo = newUserInfo;
NSString *alertMessage = [[newUserInfo objectForKey:#"aps"] objectForKey:#"alert"];
UIApplicationState state = [application applicationState];
UIAlertView *alertView = nil;
// for background banner use
switch (state) {
case UIApplicationStateActive: // when app is alive, show alert to notify user
alertView = [[UIAlertView alloc]initWithTitle:NSLocalizedString(#"SmartHome",nil) message:NSLocalizedString(alertMessage,nil) delegate:self cancelButtonTitle:NSLocalizedString(#"Close",nil) otherButtonTitles:NSLocalizedString(#"Open",nil),NSLocalizedString(#"Mark as Read",nil), nil];
[alertView show];
break;
case UIApplicationStateBackground: // app is in background mode
// user tap the banner or tap the mark as read button, code will go here
[Functions addNotificationDataInDatabase:[newUserInfo objectForKey:#"uniqueID"] type:[newUserInfo objectForKey:#"deviceType"] event:[newUserInfo objectForKey:#"event"] time:[newUserInfo objectForKey:#"time"] read:#"0" description:alertMessage];
break;
case UIApplicationStateInactive: // tapping the banner
//NSLog(#"UIApplicationStateInactive");
// go to notification view
// because will go to the notification view detail, set status to read
[self gotoNotificationView:userInfo]; //uniqueID
break;
default:
break;
}
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
handler(UIBackgroundFetchResultNoData);
// send post notification for updating the badge, will get the notification in foreground
[[NSNotificationCenter defaultCenter] postNotificationName:#"APNsNotification" object:self userInfo:nil];
}
Does anyone have this problem before? Did I miss something?
Please help me!!
u can put alert and check launchOptions
if (launchOptions) {
if ([launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"]) {
[self application:self didReceiveRemoteNotification:[launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] fetchCompletionHandler:^(UIBackgroundFetchResult result) {
}];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)newUserInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) {
NSString *str = [[userInfo objectForKey:#"aps"] objectForKey:#"alert"];
}
}

Issue with implementing badges in ios

I am working in ios app in phonegap with pushnotification.i have added the below code in Appdelegate+notification.m
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
PushPlugin *pushHandler = [self getCommandInstance:#"PushPlugin"];
[pushHandler didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"didReceiveNotification");
// Get application state for iOS4.x+ devices, otherwise assume active
UIApplicationState appState = UIApplicationStateActive;
if ([application respondsToSelector:#selector(applicationState)]) {
appState = application.applicationState;
}
if (appState == UIApplicationStateActive) {
PushPlugin *pushHandler = [self getCommandInstance:#"PushPlugin"];
pushHandler.notificationMessage = userInfo;
pushHandler.isInline = YES;
[pushHandler notificationReceived];
} else {
//save it for later
self.launchNotification = userInfo;
}
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber + [[[userInfo objectForKey:#"aps"] objectForKey: #"badge"] intValue];
}
I am using pushNotification.java file for sending push message to our application in that i have mentioned payload.addBadge(1);
So in my app badge gets update onclick of notification Please suggest me how to do it while receiving notification

didReceiveRemoteNotification or didFinishLaunchingWithOptions do not get called in background after APN

I am sending the following APN
{"aps":{"alert":{"body":"Hello sir","action-loc-key":"Caption of the second Button"},"badge":1,"sound":"default","content-available":1},"Key1":"Value1","Key2":"Value2"}
As you see I am setting "content-available":1 as part of payload
When my application is running in foreground, everything work fine. But when my application is running in background and APN Notification comes. Notification display on screen correctly. When I click the icon , it does not call didReceiveRemoteNotification or didFinishLaunchingWithOptions
I do not know what I am missing.
My code is below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
splitViewController.delegate = self;
// Register for Remote Push Notification
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)])
{
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySetings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySetings];
[application registerForRemoteNotifications];
NSLog(#"didFinishLaunchingWithOptions called");
}
//Accept push Notification when app is not open
NSLog(#"Accept push Notification when app is not open");
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif)
{
NSLog(#"Accept push Notification when app is not open if stat ");
[self processRemoteNotificationApplicationStateActive:remoteNotif];
}
return YES;
}
-(void) sendDeviceToken:(NSString *) DeviceToken
{
NSLog(#"sendDeviceToken called");
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *deviceTokenString = [[[NSString stringWithFormat:#"%#", deviceToken] //convert NSData to NSString with stringWithFormat
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]]stringByReplacingOccurrencesOfString:#" " withString:#""]; // trim the "<>" then remove the spaces
NSLog(#"deviceTokenString : %#", deviceTokenString);
[self sendDeviceToken:deviceTokenString];
NSLog(#"didRegisterForRemoteNotificationsWithDeviceToken called");
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(#"Error in registration. Error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"didReceiveRemoteNotification called");
if ( application.applicationState == UIApplicationStateActive)
{
//App is already in the foreground
NSLog(#"App is already in the foreground");
[self processRemoteNotificationApplicationStateActive:userInfo];
}
else
{
NSLog(#"App was just brought from background to foreground");
//App was just brought from background to foreground
[self processRemoteNotificationApplicationStateActive:userInfo];
}
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"didReceiveRemoteNotification fetchCompletionHandler called");
if ( application.applicationState == UIApplicationStateActive)
{
//App is already in the foreground
NSLog(#"App is already in the foreground");
[self processRemoteNotificationApplicationStateActive:userInfo];
}
else
{
NSLog(#"App was just brought from background to foreground");
//App was just brought from background to foreground
[self processRemoteNotificationApplicationStateActive:userInfo];
}
completionHandler(UIBackgroundFetchResultNewData);
}
-(void)processRemoteNotificationApplicationStateActive:(NSDictionary *)userInfo
{
[self.myDetailViewController performAPNUpdate];
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
NSLog(#"applicationWillResignActive called");
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
NSLog(#"applicationDidEnterBackground called");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
NSLog(#"applicationWillEnterForeground called");
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
NSLog(#"applicationDidBecomeActive called");
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
NSLog(#"applicationWillTerminate called");
}
#pragma mark - Split view
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return YES;
} else {
return NO;
}
}
When you open the app by tapping on the app icon you do not get any information about the push notification. Apple expects you to sync with your own server in that case.
Thus didReceiveRemoteNotification will never be called. If your app is terminated, didFinishLaunchingWithOptions will be called but you will not get any information about the push notification.
This behaviour does not make much sense to me personally, but to work around it we have created a notification syncing webservice whenever the app is opened.
When you app is running in background and the push with content-available is received, the callback method application:didReceiveRemoteNotification:fetchCompletionHandler: will be called immediately.
When you tap on the alert and the app is opened at this point, no other callback methods will be called. That is an expected behaviour since application:didReceiveRemoteNotification:fetchCompletionHandler: was already called.
It will be weird if your log did not show application:didReceiveRemoteNotification:fetchCompletionHandler: at all.
Also, make sure UIBackgroundModes include remote-notification for silent push.

Waiting for service operation in didFinishLaunchingWithOptions AND didRegisterForRemoteNotificationsWithDeviceToken called after delay

I am not sure where exactly my question fit. Here is the issue :
I want the push notifications to be registered on application start. For which I am registering in AppDelegate didFinishLaunchingWithOptions.
sem = dispatch_semaphore_create(0);
[manager registerForPushNotifications];
dispatch_semaphore_signal(sem);
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
If I don't use GCD, return YES; of didFinishLaunchingWithOptions is called first and in that case, my my service method, which want to call from didRegisterForRemoteNotificationsWithDeviceToken for sending device token is not called.
// system push notification registration success callback, delegate to pushManager
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"content---%#", token);
[[NSUserDefaults standardUserDefaults]setObject:token forKey:#"deviceToken"];
[self registerForPushWooshNotification];
[[PushNotificationManager pushManager] handlePushRegistration:deviceToken];
}
-(void)registerForPushWooshNotification
{
NSDictionary *params = #{#"TokenId": [[NSUserDefaults standardUserDefaults]objectForKey:#"deviceToken"]
};
[_sharedHandler.requestManager POST:TGURL_PUSHWOOSH_NOTIFICATION
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *e;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[operation.responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&e];
NSLog(#"------ Registered for Pushwoosh ------");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
But as I have implemented the GCD, didRegisterForRemoteNotificationsWithDeviceToken never gets called.
Summary :
1. I have to register application on app start.
2. Web Service needs to be called on app start.
3. If GCD not used : return YES; is called first, and didRegisterForRemoteNotificationsWithDeviceToken gets called after delay.
4. If GCD used : didRegisterForRemoteNotificationsWithDeviceToken is never called.
I had searched for didFinishLaunchingWithOptions wait and didRegisterForRemoteNotificationsWithDeviceToken called after delay on google before posting this question but no success.
The problem here is that by waiting on the semaphore, you are blocking the main thread, and the callback you are expecting to happen later will be delivered on the main thread. Since you're blocking the main thread, the callback will never happen. If you want your app to not do anything until that callback is received, you have to set that up another way.
The solution that would be philosophically closest to what you have now would be to spin the main run loop while waiting waiting for the callback, but there are a number of different ways to do it, and that's probably not the way I would choose. That said, if you wanted to do it that way, it might look something like this:
#implementation AppDelegate
{
BOOL didRegisterCalled;
NSData* token;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application registerForRemoteNotifications];
NSLog(#"registerForRemoteNotifications called. waiting for callback.");
while (!didRegisterCalled)
{
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
}
NSLog(#"Register call back happened, and execution resumed");
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
didRegisterCalled = YES;
token = [deviceToken copy];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
didRegisterCalled = YES;
token = nil;
}
#end
The simplest way would be to split your startup tasks into a separate method and have the callback call that method. (FWIW, this is probably the approach I would choose.) That might look like this:
#implementation AppDelegate
{
BOOL didRegisterCalled;
NSData* token;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(#"Calling registerForRemoteNotifications and deferring the rest of app startup.");
[application registerForRemoteNotifications];
return YES;
}
- (void)theRestOfTheAppStartupProcess
{
NSLog(#"Finishing app startup now that registration has happened.");
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
token = [deviceToken copy];
if (!didRegisterCalled)
{
didRegisterCalled = YES;
[self theRestOfTheAppStartupProcess];
}
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
token = nil;
if (!didRegisterCalled)
{
didRegisterCalled = YES;
[self theRestOfTheAppStartupProcess];
}
}
#end
Another way might be to set up a dispatch queue, suspend it, and then have the callback resume it. That might look like this:
#implementation AppDelegate
{
dispatch_queue_t appStartupQueue;
NSData* token;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
appStartupQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_suspend(appStartupQueue);
dispatch_set_target_queue(appStartupQueue, dispatch_get_main_queue());
dispatch_async(appStartupQueue, ^{
[self theRestOfTheAppStartupProcess];
});
NSLog(#"Calling registerForRemoteNotifications and deferring the rest of app startup.");
[application registerForRemoteNotifications];
return YES;
}
- (void)theRestOfTheAppStartupProcess
{
NSLog(#"Finishing app startup now that registration has happened.");
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
token = [deviceToken copy];
if (appStartupQueue)
{
dispatch_resume(appStartupQueue);
appStartupQueue = nil;
}
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
token = nil;
if (appStartupQueue)
{
dispatch_resume(appStartupQueue);
appStartupQueue = nil;
}
}
#end
But what you have currently is going to produce a deadlock.

Navigate to particular view controller when user tap the notification IOS7

Hi i have added push notification in my application and I want to view particular ViewControllers when the user tap the notification. In my app delegate m file I'm trying to get the register the device token to my server and from my server I'm using the php script to get the device token from server and I'm sending the notification.
The problem here I'm trying to view a particular view controller when the user taps on the notification its not working i have tried many different methods nothing had worked.
Here I'm view the popup like to send notification from the app when user trying to install application for the first time.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNone)];
return YES;
}
- (void) clearNotifications {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
Here I'm storing the device to token to my server.
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
const char* data = [deviceToken bytes];
NSMutableString * token = [NSMutableString string];
for (int i = 0; i < [deviceToken length]; i++) {
[token appendFormat:#"%02.2hhX", data[i]];
}
NSString *urlString = [NSString stringWithFormat:#"url?token=%#",token];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSLog(#"token %#",urlString);
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSLog(#"request %# ",urlRequest);
NSData *urlData;
NSURLResponse *response;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];
NSLog(#"data %#",urlData);
[self clearNotifications];
// NSLog(#"token ",sendUserToken);
}
Here I'm trying to view the particular method when user tap the notification.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
updatepoliticalViewController *ringingVC = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"updatepoliticalViewController"];
[self.window.rootViewController presentViewController:ringingVC animated:YES completion:NULL];
}
My particular view controller name is updatepoliticalViewController its a navigation view controller please tell me in this above code where I'm doing wrong how to resolve this issue.
Thanks
When the app is in foreground state it call
application:didReceiveRemoteNotification:
but if it's not and the app is launched, for example, by swiping the alert in notification center
application:didFinishLaunchingWithOptions:
is called with key.
The good way is to call
application:didReceiveRemoteNotification:
from
application:didFinishLaunchingWithOptions:
I believe this should help
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
[self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];
}
// YOUR CODE...
return YES;
}
// EXTENDED
Try get storyboard like that:
// Make sure the name match
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
Create your object from mainstoryboard:
updatepoliticalViewController *ringingVC = [mainstoryboard instantiateViewControllerWithIdentifier:#"updatepoliticalViewController"];
And try set new root view controller
[self.window setRootViewController: ringingVC];
1) When application is running in background and When application is running in foreground
application:didReceiveRemoteNotification: method will called as below.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateInactive)
{
//opened from a push notification when the app was on background
NSLog(#"userInfo->%#",[userInfo objectForKey:#"aps"]);
}
else if(application.applicationState == UIApplicationStateActive)
{
// a push notification when the app is running. So that you can display an alert and push in any view
NSLog(#"userInfo->%#",[userInfo objectForKey:#"aps"]);
}
}
2) When application is not launched (close) than application:didFinishedLaunchWithOptionsmethod will called.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (launchOptions != nil)
{
//opened from a push notification when the app is closed
NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfo != nil)
{
NSLog(#"userInfo->%#",[userInfo objectForKey:#"aps"]);
}
}
else{
//opened app without a push notification.
}
}

Resources