I'm able to send push notifications to iOS devices. There is a "Close" button on the notification and a "View" button. When the user hits the "View" button the app opens up to the root view controller. Within the app there is a news section. Let's say the notification is to alert the user that there is a new news story for them to see. If they hit "View", the root view controller will show, instead of the news view controller. How would I go about opening the news view controller? Facebook uses this a lot. Would this be something to change on the server or within the app? Thanks for your help!
For iOS 8+ action button in notifications:
For local notification, appDelegate calls this method when a button on the notification (lock screen or banner) is pressed:
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forLocalNotification:(UILocalNotification *)notification
completionHandler:(void (^)())completionHandler
For push notification, appDelegate calls this method when a button on the notification (lock screen or banner) is pressed:
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)userInfo
completionHandler:(void (^)())completionHandler
You have to check the launch options in your application delegate:
application:didFinishLaunchingWithOptions
There you can obtain the payload dictionary of the push notification.
Related
iPhone version - 5.1 (9B176)
Below is the series of events during Local Notification where in which didFinishLaunchingWithOptions method is not invoked.
App is running in background.
Got local notification - simple notification no dialog.
Click on the app icon which shows the badge number.
Expected as per Apple 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 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
Actual :
didFinishLaunchingWithOptions NOT invoked. But applicationWillEnterForeground and applicationDidBecomeActive were invoked.
You are correct. The behavior is inconsistent with the documentation. Putting the documentation aside and focusing on actual behavior; The crux of the matter seems to be this: If your app becomes active by the user interacting with the notification you will receive a pointer to the notification, if the user taps your application icon directly you will not.
To illustrate. If you present an alert style notification and the user taps the action button, or if, as in your case, you present a banner notification and the user taps on that you will receive a pointer to the notification in one of two ways:
If your application was in the Not-Running state:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UILocalNotification *launchNote = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (launchNote){
// I recieved a notification while not running
}
}
If your application is running in any state:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
// I recieved a notification
}
In the case where a user elects to cancel an alert style notification, that notification is gone.
The truly annoying an inconsistent part is that if you present a banner notification and the user taps your icon you seem to have no way of retrieving a reference to the presented notifications in the notification center. i.e. they do not appear in the [[UIApplication sharedApplication] scheduledLocalNotifications] array, presumably because they are no longer scheduled but are now presented.
So in short; The documentation is wrong. And there are other annoying inconsistencies. If this behavior is a problem for you you should file a bug with Apple.
Is there a delegate method or some way to get the event when a user clears my applications notifications from the Notification drop-down menu? The UIApplication delegate
-(void)application:(UIApplication)application didReceiveLocalNotification:(UILocalNotification *)notification
is only called when they select an event from the list but it isn't called when the list is cleared.
No, if a user clears your notification, it's the same as if it never arrived.
If you clear notification or swipe on notification message this method will be called in appdelegate.m file.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
//When notification is pressed on background it will enter here
//Get strings based on information on your json payload for example
if([[userInfo objectForKey:#"keyword"] isEqualToString:#"value"]){
//redirect/push a screen here for example
}
I have a button ON/OFF in my viewcontroller that plays some music when it is turned on by the user. Now if the user clicks the iPhone home button and re-launches my app again, the button is shown as "ON" but there is no music playing. So the user has to hit ON-OFF-ON again for music to start playing again.
Anyone know how can I call my ON/OFF view controller button so that I can set it to OFF when app enters background and set it to ON and play the music when it enters forground in these app delegates?
I know I need to write to a plist file the button & music state on applicationDidEnterBackground. I don't know how can I get to those action from appdelegate since they are defined in my viewcontroller.
Similary, when the app enters the foreground I will read the saved plist file and then set the state of music and button again. Again, I don’t know how to call my controller methods from delegate.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Inside applicationDidEnterBackground");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(#"Inside applicationWillEnterForeground");
}
One possible methodology is to send a message from the app delegate to the view controllers to save or restore state. Then the view controller, which have access to their internal state, can implement any needed save and restore methods.
If the app delegate does not directly contain a reference to the active view controller, it can send the message down the chain, to root view controller, which can then send a message to the next view controller, and etc., each controller saving anything it considers important on the way down.
All you need to do is subscribe to the UIApplicationDidEnterBackgroundNotification notification in your view controller
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleEnteredBackground:)
name: UIApplicationDidEnterBackgroundNotification
object: nil];
Theres also a notification for DidEnterForeground too.
I want to do something like Twitter app: when someone write me I receive the push notification; if I "slide on the notification" the app starts, but not in the normal stream, it starts in a specific view with the tweet that someone wrote me!
In my app I have something like an RSS reader, and the push notification arrives when there is a new news.
So, I want to open the "single news view", and not the main view (that's happening now).
What can I do?
Thanks
You can do two things.
One is to check the launchOptions dictionary of the UIApplicationDelegate method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
to see if the app was launched via a user clicking on a notification. If so, then in that method you can push the appropriate view controller onto the stack, just as you would normally with in-app usage.
If the app is already open, but in the background then the same theory applies but instead use the UIApplicationDelegate method
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
See this link for information on handling incoming notifications.
Please help me understanding this:
When home button is pressed and iPhone application goes in the background and a Push Notification is received. There is an alert being displayed which contains the message for that notification with "View" button on it. Where this alert is coming from -- IOS generating it?
In my code I wrote code for showing alert when notification comes in inside my
- (void)application:(UIApplication *)iApplication didReceiveRemoteNotification:(NSDictionary *)iUserInfo {
method. And on this alert action I am showing my view controller. Now, I am ending up showing two alerts -- One which is coming from IOS (I believe) and on tap of view is taking me to last visited page of my app and Second which I created and on tap of View is taking me to desired page.
Please help understanding this.
If I understand you correctly, you get two AlertViews instead of one if you click on View. Then you should check whether the application is active or not. Have a look at the UIApplication Class Reference
UIApplication Class Reference #applicationState
- (void)application:(UIApplication *)iApplication didReceiveRemoteNotification:(NSDictionary *)iUserInfo {
if([application applicationState] == UIApplicationStateActive) {
//show alert
}
}
Oliver Drobnik wrote a very detailed examination of the possible message flows when dealing with notifications and app state. The short version - if your apps not frontmost, the OS displays a notification and may launch your app in response to user actions; if your app is frontmost, you're responsible for everything, be it displaying an alert or some other processing.
http://www.drobnik.com/touch/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/