notification launch custom method/class - ios

just want to make sure i'm on the right path.
I'm creating a local notification as an alarm clock. when the user hits button... I want it to DO STUFF.
I'm thinking I have to call my method in
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
.. .for when the application is closed
(void)applicationWillEnterForeground:(UIApplication *)application
... for when the application is in the background... when user hits okay
Is there a better way to do what I'm trying to accomplish... DO STUFF when user hits okay on notification?
thanks in advance

According to the documentation of local and push notifications, you should call application:didFinishLaunchingWithOptions: in both cases :
Handling Local and Remote Notifications
Let’s review the possible scenarios when the operating delivers a
local notification or a remote notification for an application.
The notification is delivered when the application isn’t running in the foreground.
In this case, the system presents the notification, displaying an alert, badging an icon, perhaps playing a sound.
As a result of the presented notification, the user taps the action button of the alert or taps (or clicks) the application icon.
If the action button is tapped (on a device running iOS), the system launches the application and the application calls its
delegate’s application:didFinishLaunchingWithOptions: method (if
implemented); it passes in the notification payload (for remote
notifications) or the local-notification object (for local
notifications).
If the application icon is tapped on a device running iOS, the application calls the same method, but furnishes no information about
the notification .

They can not be forced to call. only Monitoring.
UIApplicationDelegate Protocol
These methods provide you with information about key events in an
application’s execution such as when it finished launching, when it is
about to be terminated, when memory is low, and when important changes
occur. Implementing these methods gives you a chance to respond to
these system events and respond appropriately.
If you want you're ViewController get Notification there method. try this
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidFinishLaunching:) UIApplicationDidFinishLaunchingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
- (void)applicationDidFinishLaunching:(NSNotification *)noti
{
//do stuff
}
- (void)applicationEnterForeground:(NSNotification *)noti
{
//do sutff
}

Related

Detect user tap on local notification

I show my local notification like this periodically.
UILocalNotification *notification = [[UILocalNotification alloc]init];
[notification setAlertBody:#"Test test"];
[notification setUserInfo:#{#"test": #"test"}];
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
I need to detect back that notification and I plan to write here.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
It always call that function whether user tap on notification or it automatically call in foreground.
So, I separate using this.
if (application.applicationState == UIApplicationStateActive)
When I show notification center, it become InActive. But, it still call didReceiveLocalNotification. I can't differentiate whether user tap on notification from notification center or because of my periodic posting notification.
How can I really know that I tap on notification (Either from InActive State or Background State) in didReceiveLocalNotification?
Assuming that I understood your issue correctly, I stumbled on the same obstacle and couldn't find a super clean solution.
So the situation where the following method
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
is called and applicationState is equal to UIApplicationStateInactive happens in two cases:
the app is in the foreground and the notification has just been fired
the notification has been fired some time ago, notification center is pulled down and user tapped on the notification
One way to distinguish these two cases is to check the notification's fireDate:
notification.fireDate.timeIntervalSinceNow < 0.5
If this expression is true, it's very likely that the first case happened. If the expression is false, it's very likely that the second case happened.
This solution depends on the system delivering the notification without delay and/or the user not being fast enough to click the notification in the notification center under 500ms since the notification's firing. I'm not sure how likely is it for a firing delay to happen. I guess it's possible if the device is under some kind of processing load.
I hope there is a cleaner solution, hopefully someone will share it.
First of all, read this from Apple Documentation:
The user taps a custom action button in an iOS 8 notification. In this
case, iOS calls either
application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
or
application:handleActionWithIdentifier:forLocalNotification:completionHandler:.
In both methods, you get the identifier of the action so that you can
determine which button the user tapped. You also get either the remote
or local notification object, so that you can retrieve any information
you need to handle the action.
The user taps the default button in the alert or taps (or clicks) the
app icon. If the default action button is tapped (on a device running
iOS), the system launches the app and the app calls its delegate’s
application:didFinishLaunchingWithOptions: method, passing in the
notification payload (for remote notifications) or the
local-notification object (for local notifications). Although
application:didFinishLaunchingWithOptions: isn’t the best place to
handle the notification, getting the payload at this point gives you
the opportunity to start the update process before your handler method
is called.
Second, this is how you can differentiate whether didReceiveLocalNotification: is called from active or inactive state:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplicationState appState = UIApplicationStateActive;
if ([application respondsToSelector:#selector(applicationState)])
appState = application.applicationState;
if (appState == UIApplicationStateActive)
{
}
else
{
}
}
application:didReceiveLocalNotification:
Sent to the delegate when a running app receives a local notification.
Check this:
iOS UILocalNotification - No delegate methods triggered when app is running in background and the icon is clicked upon notification
Use KVO key-value-observing to know and do something when the button is tapped.

Sliding to open on ios does not do the needed job

Sliding from the lock screen and/or pressing a notification from the notifications page... do both pass from applicationDidFinishLunchingWithOptions when the app is totally closed?
My concern is because, when the app is closed and not in background, whenever I press on the app from the notification, my app opens and goes where it has to go... but whenever I press slide to open, the app opens but it does not go to the page it should go.
The docs say that if the action button on the notification is pressed, it calls application:didFinishLaunchingWithOptions and passes in the notification payload. Later it says if the app is running in the foreground, it delivers the notification via application:didReceiveRemoteNotification:. This implies to me that when the app is backgrounded or not running, then application:didFinishLaunchingWithOptions is called. Otherwise, application:didReceiveRemoteNotification: is called.
application:didFinishLaunchingWithOptions: will only be called if your app is not launched already. While it is true that the options will include info on notifications if that is what ended up launching the app, what you want is to handle your local notification logic here:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

Handling local notifications when the user presses the icon instead of the alert

Here is the situation that I want to handle quoted from Apple's documentation.
As a result of the presented notification, the user taps the action button of the alert or taps (or clicks) the application icon.
If the action button is tapped (on a device running iOS), the system launches the application and the application calls its delegate’s application:didFinishLaunchingWithOptions: method (if implemented); it passes in the notification payload (for remote notifications) or the local-notification object (for local notifications).
If the application icon is tapped on a device running iOS, the application calls the same method, but furnishes no information about the notification . If the application icon is clicked on a computer running OS X, the application calls the delegate’s applicationDidFinishLaunching: method in which the delegate can obtain the remote-notification payload.
How do I handle this situation if there is no information about the notification?
If I understand you correctly, it sounds like you have a UILocalNotification that has been fired, but you need to still handle it if the user taps the application icon instead of the notification. Correct?
If this is the case, then to my knowledge you won't be able to handle the notification from the app delegate, because the app is not being launched or brought out of the background by the notification, but instead by the user's interaction.
However, if you are setting a badgeNumber on the application with the notification then you could try something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
} else if ([UIApplication sharedApplication].applicationIconBadgeNumber > 0) {
// Assume that user launched the app from the icon with a notification present.
}}
You may also have to check the badgeNumber in - (void)applicationDidBecomeActive:(UIApplication *)application as well.
Improve to #Aron Crittendon answer:
Consider also to handle that in applicationDidBecomeActive:
-(void)applicationDidBecomeActive:(UIApplication *)application
{
if ([UIApplication sharedApplication].applicationIconBadgeNumber > 0) {
//application is in background, fired notification and user tapped app icon with badge
}
}
As the documentation states, if you tap the icon on iOS (and not the notification's alert/banner) then the same method is called but you get no notification information. There is no way to handle a local notification simply by tapping the app icon.

How can you get the payload of a push notification if app is already running in the background when the user taps the notification?

If a push notification is displayed to the user and the user taps it and the app is brought to the foreground from a background state then how can the app get the payload of the notification?
Because the app is already running didFinishLaunchingWithOptions: won't get called and because the app was in the background when the push arrived didReceiveRemoteNotification: won't have been called.
There are two places so I usually make a method that handles both something like this:
- (void)handleMessageFromRemoteNotification:(NSDictionary *)userInfo
Then in: application:didFinishLaunchingWithOptions:
if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {
[self handleMessageFromRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];
}
also in: application:didReceiveRemoteNotification:
[self handleMessageFromRemoteNotification:userInfo
If you want to do something different if the app is running check application.applicationState == UIApplicationStateActive in didReceiveRemoteNotification
According to Apple documentation the method didFinishLauchingWithOptions: is called when the user taps the action button of the notification.
As a result of the presented notification, the user taps the action
button of the alert or taps (or clicks) the application icon. If the
action button is tapped (on a device running iOS), the system launches
the application and the application calls its delegate’s
application:didFinishLaunchingWithOptions: method (if implemented); it
passes in the notification payload (for remote notifications) or the
local-notification object (for local notifications).
Then in this method it is easy to recover the content of the notification by doing for example :
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
[viewController displayItem:itemName]; // custom method
app.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
}
"because the app was in the background when the push arrived didReceiveRemoteNotification: won't have been called."
This, or didReceiveRemoteNotification:withExpirationHandler, should get called if the app is in the background and gets switched to the foreground when the user taps on the notification.
However I got into a situation when this wasn't working as the reason was the content of the push was incorrect, I can't remember the details but double check what's in there.

Spurious UIApplicationDidBecomeActiveNotification notification

I am able to register for UIApplicationDidBecomeActiveNotification and properly receive events. But sometimes I receive these notifications WHILE the app is still running. I suspected memory problems to trigger an app resign/resume but could not confirm this was the case (I saw once a memory warning at the same time). Any reason why these methods would be called while the app is running (no call, no lock, etc.)?
I am registering for these notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appDidBecomeActiveNotif:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appWillResignActiveNotif:) name:UIApplicationWillResignActiveNotification object:nil];
(This is done once in a singleton constructor using dispatch_once)
The corresponding functions:
-(void)appDidBecomeActiveNotif:(NSNotification*)notif
{
NSLog(#"appDidBecomeActiveNotif called");
}
-(void)appWillResignActiveNotif:(NSNotification*)notif
{
NSLog(#"appWillResignActiveNotif called");
}
Here are some logs:
2013-04-11 09:28:11.401 App[1499:907] appWillResignActiveNotif
2013-04-11 09:28:13.505 App[1499:907] appDidBecomeActiveNotif
This is what the docs says about those notifications:
UIApplicationDidBecomeActiveNotification
Posted when the application becomes active.
An application is active when it is receiving events. An active application can be said to have focus. It gains focus after being launched, loses focus when an overlay window pops up or when the device is locked, and gains focus when the device is unlocked.
UIApplicationWillResignActiveNotification
Posted when the application is no longer active and loses focus.
An application is active when it is receiving events. An active application can be said to have focus. It gains focus after being launched, loses focus when an overlay window pops up or when the device is locked, and gains focus when the device is unlocked.
So, are there any overlay window pop ups or are you locking the device or anything like that?
Also, why not use the methods in the AppDelegate to listen to those events?
EDIT
The problem, it seems, is MapKit's pop up asking the user to use it's location.

Resources