Crash when handling remote notification when app not running - iphone

I receive a remote notification and according to the type of notification, change navigation controller's view controllers.
It all works fine when the app is in the foreground, or when the app is in the background but not completely closed (from multi-tasking bar).
But, when the app is closed, and receives a remote notification it crashes as soon as it opens. Am I doing wrong with the way I am setting up the ViewControllers?
Here's some code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions {
// Push required screens into navigation controller
UILocalNotification *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
//Accept push notification when app is not open
if (remoteNotif) {
[self handleRemoteNotification:application userInfo:remoteNotif.userInfo];
return YES;
}
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
-(void) handleRemoteNotification:(UIApplication *)application userInfo:(NSDictionary *)userInfo {
application.applicationIconBadgeNumber = 0;
NSMutableArray *viewControllers = [NSMutableArray array];
[viewControllers addObject:driverWaitViewController];
[viewControllers addObject:newJobsViewController];
[navigationController setViewControllers:viewControllers];
}

I got this resolved, and it has nothing to do with view controllers, as I thought.
The issue was in the following lines. I was sending in remoteNotif.userInfo rather than remoteNotif itself. Also, remoteNotif is obviously not of type UILocalNotification. It is a NSDictionary object.
Before
UILocalNotification *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
[self handleRemoteNotification:application userInfo:remoteNotif.userInfo];
Should be
NSDictionary *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
[self handleRemoteNotification:application userInfo:remoteNotif];

if you close the app which start from xcode debug mode, and when the app start with push notification(closed app) if the your phone connected to mac(still your phone in debug mode with xcode) it will be crash. test this senario with unplugged phone.

You aren't properly initializing your application when receiving a notification.
Change the application:didFinishLaunchingWithOptions: method to this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
// Push required screens into navigation controller
NSDictionary *notif= [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
//Accept push notification when app is not open
if (notif) {
[self handleRemoteNotification:application userInfo:notif];
}
return YES;
}

Related

App crashes when didFinishLaunchingWithOptions is called

I have an the app when notification is fired i get a notification bar when the app is in background ,when i tap on that bar it navigates into tableview of the notification set . When i quit the app from background i am receiving notification but when tap on the notification bar the app is getting crashed since its not getting indexpath of the tableview.
When the app is quit in background and reloading the app should enter didfinishlaunching.
In appDidFinishLaunching i am calling the method which navigates into tableview
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[PPViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil] ;
UILocalNotification *notification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
int remedyID = [[notification.userInfo objectForKey:kRemindMeNotificationRemedyIDKey] intValue];
NSDictionary *reminderDetails =[NSDictionary dictionaryWithObjectsAndKeys:notification.userInfo,#"kRemindMeNotificationDataKey",[NSNumber numberWithInt:remedyID],kRemindMeNotificationRemedyIDKey,nil];
[_viewController goToReminder:reminderDetails showNotification:YES];
}
[application setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
self.viewController = [[PPViewController alloc] initWithNibName:#"PPViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
**This is the code which navigates into tableview in another viewcontroller**
- (void)goToReminder:(NSMutableDictionary *)reminderDictionary showNotification:(BOOL)shouldShowNotification
{
NSIndexPath *selectedSymptIP = [NSIndexPath indexPathForRow:selectedSymptomIndex inSection:keyIndexNumber];
[self tableView:symptomsTableView didSelectRowAtIndexPath:selectedSymptIP];
}
When you quit the app and your app starts again, your viewController is not yet set up. When launching from a notification, you need to check if you are resuming from the background, or launching normally.
Look at applicationWillEnterForeground and applicationDidBecomeActive in the UIApplicationDelegate protocol reference for how to handle resuming your app from various states. Also see: http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW3
I was able to solve the problem ..the crash was occurring since wrong xib file was loaded .

Clearing the badge when received Push Notification

How can I clear the badge which appears on application icon when I receive Push Notification? I want to clear it once user has either tapped on "View" of Push notification alert or has tapped on the app icon.
I suspect you are talking about the SpringBoard's badge:
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]
Badge count set Zero
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]
Cancel all local notifications with this code:
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Cancel one local notification with this line of code:
[[UIApplication sharedApplication] cancelLocalNotification:theNotification];
here theNotification is a UILocalNotification object, so in order to cancel a specific notification, you need to hold on to it's UILocalNotification.
Check this.
For Mac OS X Lion, it's:
[NSApp dockTile].badgeLabel = #"";
(Lion supports badge-type push notifications.)
From Apple's documentation, set the application.applicationIconBadgeNumber to the number you want displayed on the badge. If you set it to 0, it will be cleared.
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
[viewController displayItem:itemName]; // custom method
application.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
}
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
Reference - Scroll down to the Handling Local and Remote Notifications section just above listing 2.4

iphone: Set badge on a tabbarItem when receiving a PUSH message, when the app is inactive

I have a application that uses PUSH. But I have one problem when the application is inactive/in the background.
When the PUSH messages come and the user clicks on Close, the badge is set on the application-icon.
But I also want to set a badge on a tabBarItem.
I have this code that saves the PUSH
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if (application.applicationState == UIApplicationStateInactive) {
//Save the PUSH until the app is active.
newPush = [userInfo copy];
}
}
And in:
- (void)applicationDidBecomeActive:(UIApplication *)application
I have the following code:
//Check if there is new PUSH messages.
if (newPush!=nil) {
//There is a new PUSH!
NSInteger badge = [[[newPush objectForKey:#"aps"] objectForKey:#"badge"] intValue];
if (badge > 0) {
//Set badge-numbers to 'badge'
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge];
[[[[[self tabBarController] tabBar] items] objectAtIndex:3] setBadgeValue:[NSString stringWithFormat:#"%d",badge]];
}
else {
//Set badge-numbers to zero
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
[[[[[self tabBarController] tabBar] items] objectAtIndex:3] setBadgeValue:nil];
}
}
My code for handling the PUSH when the application is active works fine and the badges are set both on the application-icon and on the tabBarItem.
Someone know what's wrong?
Thanks in advance!
If the application is inactive, didReceiveRemoteNotification is not executed. The only way the notification data can reach your app in this case is if the user taps on the notification to open the app. Then, when the app is launched, you can get the notification data in application:didFinishLaunchingWithOptions: by using this code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions {
NSDictionary *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
//Accept push notification when app is not open
if (remoteNotif) {
[self handleRemoteNotification:application userInfo:remoteNotif];
return YES;
}
return YES;
}

iPhone didFinishLaunchingWithOptions Method

So i'm trying to use this method to load a certain theme based on what the user chose in the settings bundle. When I insert NSLog it will load the default them (Modern Theme), but it will never change to the Pink Theme.
Is this method loaded every time the app is launched, even if the app is still running in the background.
Otherwise, where else could I do this, if I want to use the settings bundle.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *userDefaultsDefaults = [NSDictionary dictionaryWithObjectsAndKeys: #"Modern Theme", #"theme", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsDefaults];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
theme =[defaults objectForKey:#"theme"];
NSLog(#"%#", theme);
if ([theme isEqualToString:#"Modern Theme"]) {
viewController = [[viewTwo alloc] initWithNibName:#"viewTwo" bundle:nil];
}
else {
viewController = [[viewOne alloc] initWithNibName:#"viewOne" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Have you tried putting your code in applicationDidBecomeActive:? That one is guaranteed to be called whether on the initial launch or resuming from the background.
Reference docs.
The method
- (void)applicationWillResignActive:(UIApplication *)application
is fired when the app is resumed from the background.
I'd nearly load the theme in the ViewController's
-(void)viewDidAppear:(BOOL)animated
method.

Push notification and view button action[iphone sdk APNS]

I am developing a Push Notification enabled application for Iphone.
In My application I have two List View (UITableView)
1st for Category List and the 2nd is Contents List.
User clicks the desired category then the contents related to that category will be displayed then user will choose the contents and the contents will be displayed in detail view(generally a UIWebView).
Push notification is successfully coming in my application.
My requirement is:-
After VIEW button of Push alert is clicked application will directly display a particular
detail view (UIWebView)[Omitting category and contents list].
I have a unique ID for category and contents.
So will you please guide me how to relate a particular content with Push Notification and directly display of that content.
Thanks and regards.
HI,
I have solved the problem.
This is what I have done.
When application received push notification, it stored notification in launchOptions NSDictionary.
/* Push notification received when app is not running */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString *params=[[launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:#"contTag"];
if ([params length] > 0 ) {//app launch when VIEW button of push notification clicked
//do some processing
........
WebViewController *webViewController =
[[WebViewController alloc] initWithNibName:#"WebView" bundle:[NSBundle mainBundle]];
// Put your custom code
[[self navigationController ] pushViewController:webViewController animated:YES];
[window addSubview:navigationController.view];
/* Remote Notification Received while application was open. */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"remote notification: %#",[userInfo description]);
NSString *contentsInfo = [userInfo objectForKey:#"contTag"];
NSLog(#"Received contents info : %#", contentsInfo);
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
NSString *alert = [apsInfo objectForKey:#"alert"];
NSLog(#"Received Push Alert: %#", alert);
NSString *sound = [apsInfo objectForKey:#"sound"];
NSLog(#"Received Push Sound: %#", sound);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
//-----------------------APNS HANDLE----------------
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive){
NSLog(#" It is in active state");
application.applicationIconBadgeNumber = [[apsInfo objectForKey:#"badge"] integerValue];
}
else {
if ([contentsInfo length] > 0 ) {
// Do whatever u want for push notification handle
}
NOTE:
Here contTag is a key set in server side for pay load of push notification.
U can set any key in server side.
Hope it will help some body.
Thanks