I am using local notification for alarm system but I am facing some problem while handling local notification, When i clicked on alarm notification (When app is closed) its launches app but the problem is it should go to didFinishLaunchingWithOptions function but it's not going inside any of the function in appDelegate (I used breakpoints to check).
I'm using story board with navigation controller, I want to open a specific view controller on notification click when app is closed.
but when I'm launching that app normally it's going inside didFinishLaunchingWithOptions function.
Please suggest.
Any help would be appreciated.
main.m
#import "DEMOAppDelegate.h"
int main(int argc, char * argv[])
{
#autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([DEMOAppDelegate class]));
}
}
DEMOAppDelegate.m
#import "DEMOAppDelegate.h"
#implementation DEMOAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *localNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif)
{
NSLog(#"Recieved Notification %#",localNotif);
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:notification.alertAction message:notification.alertBody delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
#end
It's not possible, when your app is not running notification it will not react on notification directly.
didFinishLaunchingWithOptions will contain information about notification only when user opened your app through this notifcation. If he cancels it and opens your app through dashboard icon you are not gonna see this in this method.
Unfortunatelly if you need to react on all notification that happened from last time the user opened the app, only way is to build your own tracking logic and get all events that were in the past based on time.
Also there is no way to even get a list of notification you scheduled for your app, so usually it is a good idea to build in time-based event logic and use notification on top of it, but all the logic happens on your own time-based code. This way even if user disable notifications your critical logic will work.
When the application is running in background you will get notification through application:didReceiveRemoteNotification. You can gather those notifications inside your app, and process them on applicationDidBecomeActive if you want to do anything specific inside your application for them after user comes back to the app from background.
Related
I have a app to which i can send push notifications using pushbots. The user is able to receive the notification and on clicking it he/she can open the app. However the badge notification still shows that there is a notification. How would i set my notification badge to 0.
This is my appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for Remote Notifications
[Pushbots sharedInstanceWithAppId:#"5503e09a1d0ab1481f8b45a1"];
NSDictionary * userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(userInfo) {
// Notification Message
NSString* notificationMsg = [userInfo valueForKey:#"alert"];
// Custom Field
NSString* title = [userInfo valueForKey:#"title"];
NSLog(#"Notification Msg is %# and Custom field title = %#", notificationMsg , title);
}
return YES;
}
-(void)onReceivePushNotification:(NSDictionary *) pushDict andPayload:(NSDictionary *)payload {
NSString* message = [pushDict valueForKey:#"alert"];
UIAlertView *alertMessage = [[UIAlertView alloc] initWithTitle:#"New Event !" message:message delegate:self cancelButtonTitle:#"Open" otherButtonTitles: #"I will check later",nil];
[alertMessage show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
Pushbots * pushbots = [Pushbots sharedInstance];
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Open"]) {
[pushbots OpenedNotification];
}
}
- (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.
}
- (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.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
You can call this in your application :
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
Obviously this needs a little more work. If you're dealing with messages for example, you'd need to decrement the badge number by the number of messages read and make sure to not go below zero.
You can also use the "badge" key to modify the current badge through the notification payload itself.
for example use
{..., "badge" : "increment", ...}
or
{...,"badge" : 3, ...}
The first one would be the most frequent version i'm guessing.
But if your app is fairly simple, then just call this and your badge will be set to zero.
I'd advise you to update your pushbots lib to 1.1 and use the following method which will clear the badge locally and on the server:
[[Pushbots sharedInstance] clearBadgeCount];
For Swift 3
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
Pushbots.sharedInstance().clearBadgeCount()
}
func applicationWillEnterForeground(application: UIApplication)
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
Pushbots.sharedInstance().clearBadgeCount()
}
Objective C
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
[[Pushbots sharedInstance] clearBadgeCount];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
[[Pushbots sharedInstance] clearBadgeCount];
}
We are working on iPhone app and we have implemented push notification functionality. When the app is inactive, any notification received shows an alert and the badge icon counter gets incremented. When the user clicks either on the app's icon or on the alert, the app becomes active and everything works fine.
What we want is this: On new notification, whenever a user clicks on the app icon, it should open a specific page (e.g. the Notifications page). Currently, when the app becomes active, it shows the last previously open page.
How can I redirect the app (on foreground) to a specific page?
assume that this is your PayLoad
{"aps":{"alert":"Hai User","type":"center","badge":1,"sound":"default"}}
the didReceiveRemoteNotification method handle the payload
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
// this is used for clear the count when user press the notification.
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
//When notification is pressed on background it comes here
//Get strings based on information on your json payload for example
NSMutableString *notificationType =[[userInfo objectForKey:#"aps"]objectForKey:#"type"];
if([notificationType isEqualToString:#"center"]){
//redirect/push a viewcontroler here , it automatically navigate to your VC.
profileViewController *profile = [[profileViewController alloc] initWithNibName:#"profile ViewController" bundle:nil];
[self.window.rootViewController presentViewController: profile animated:YES completion:NULL];
}
}
notification types from Apple is here
Inside your
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[self openNewViewController]; // read the userInfo from the payload and based on that open new controller
}
method you can directly push/modal/addsubview your desired page.
And inside "didFinishLaunchingWithOptions:" check for remote notification payload
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
NSDictionary *dict = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
//Call your page here
}
}
Is there any way to find out after notification is been sent, how many users clicked on the notification and how many people didnt click on the noficiation event (badge) when the app is in the background?
I am more interested to find out how many people didnt click, as people who clicked can be tracked as app will go in the foreground and request can be made vs if app is in the background, your http request may get lost.
update your app delegate code to the following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[super application:application didFinishLaunchingWithOptions:launchOptions];
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(remoteNotif)
{
//launched from push notification
}else{
//Did not launch from push notification (tapped on app icon, or from multi tasking)
//**Didn't click on notification**
}
}
and this:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if([application applicationState] == UIApplicationStateActive) {
// app was open, did not display the push alert/banner/badge
// **Didn't click on notification**
}else{
//launched from push notification
}
}
Its quite self explanatory. you can track when app was opened by tapping on a push notification and when it was opened without tapping on a notification.
I guess the closest you can come to know who didn't click your notification is by checking in your AppDelegate's didFinishLaunchWithOptions method that your app didn't get launched as a result of the user tapping a notification after you send out the notification. In other words, I think you answered your own question in your question.
In my app I am using uilocalnotifications. Every thing is ok but one thing. I need to show notifications's alertbody. If app is in foreground state it's fine, but if app is at background state and notification occurs, when i tap on that didReceiveLocalNotification doesn't get called. Obviously didFinishLaunchingWithOptions is also don't called at that time. So what should i do to handle the notification. I am using ios7 and xcode5. Thanks very much in advance if you could help me.
For an app which is not in the foreground, the local notification can subsequently be found in the
-applicationDidFinishLaunchingWithOptions method
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
//Handle local notification here.
}
You can read Apple's documentation for handling notifications here.
If the app is currently in memory, you can check it's state in the following way:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif
{
if (app.applicationState == UIApplicationStateInactive )
{
NSLog(#"app not running");
}
else if(app.applicationState == UIApplicationStateActive )
{
NSLog(#"app running");
}
}
if application is closed and notification is raised then for that you have to write below code in appdidfinishlaunching method
// Handle launching from a notification
UILocalNotification *objLocalNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (objLocalNotif)
{
NSLog(#"At the time of launching Recieved Notification %#",objLocalNotif);
//Do your stuff here
}
If application is in background and when any local notification is raised the following method of app delegate get called.
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
// Handle the notificaton when the app is running
NSLog(#"Recieved Notification %#",notif);
//do your stuff here
}
Write your code in the below method
- (void)applicationWillEnterForeground:(UIApplication *)application
it will be called when you open your application again which has not been terminated fully but still running in background
I am using local notification in my app, the only thing i care about is what exact notification the user clicked.
the method
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
triggered when the notification is received but i need to handle the notification when the user clicked on it so this is useless to me.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
triggered only when app was not running, also not what i need
i searched the net but found only handles if the app is active or not running. how can i handle it when the app is on the background?
what i need in other words is to recognise the exact notification that the user clicked when the app was running on the background
When creating your UILocalNotification, you can set the userInfo to set any associated data/unique identifiers.
Ex.
UILocalNotification *someNotification = [[UILocalNotification alloc] init];
[someNotification setUserInfo:#{ kSomeUniqueIdentifierKey : #"identifier" }];
and then,
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if ([notification.userInfo[kSomeUniqueIdentifierKey] isEqualToString:#"identifier"]) {
// We know what notification was responded to based on userInfo
}
}
The above method fires either immediately upon receiving the notification while the app was running or when the user taps the notification that fired while your app was in the background.
If you want to ignore these notifications while the app is running, you could always check the state of the application to determine if it's responding to the notification while running or in the background.
I am working with iOS 9, and the solution is to check the launchOptions within the AppDelegate didFinishLaunchingWithOptions. As follows:
// Were we launched from a local notification?
if let lo = launchOptions
{
if let ln = lo[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification
{
// Do our thing...
}
}