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...
}
}
Related
Is there a way in AppDelegate to get a queue of all the notification data? (Once the user opens the app).
As per apple documentation:
When a remote notification arrives, the system calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method. Notifications usually signal the availability of new information. In your app delegate method, you might begin downloading new data from a server so that you can update your app’s data structures. You might also use the notification to update your user interface.
You have to enable remote notification background mode, only then you will get a callback to the above mentioned method.
Try this in your app delegate:
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
For UILocalNotification, you can get received notifications by calling following function in your AppDelegate:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
// Application was in the background when notification was delivered.
}
}
If you want to find the list of local Notifications, that app has already set, check this solution.
You can check for launchOptions Dictionary, for received Notification, when App resumes on tapping a notification,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
NSLog(#"Launch Options:%#",launchOptions);
return YES;
}
First I want to know, which specific method is called when i tap on local notification. I want to open a url upon tap on notification. below is code app delegate.
Now the issue is, url opens automatically even if i don't tap on notification. Please guide me if u know that. Thank you
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notifyAlarm
{
application.applicationIconBadgeNumber = 0;
NSLog(#"Notification tapped :) ");
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.google.com.pk"]]; }
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notifyAlarm
This methos is called every time when notification fire.
To open url when tap on notification you have to check state of the app.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplicationState appState = UIApplicationStateActive;
if ([application respondsToSelector:#selector(applicationState)])
appState = application.applicationState;
if (appState == UIApplicationStateActive)
{
// Don't open Url.
}
else
{
// Open Url.
}
}
Have a look at the Local and Remote Notification Programming Guide from Apple, section "Handling Local and Remote Notifications".
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).
Later is says
[...] get the value of the applicationState property and evaluate it. If the value is UIApplicationStateInactive, the user tapped the action button; if the value is UIApplicationStateActive, the application was frontmost when it received the notification.
Try to check application.applicationState. If the app isn't active in the foreground , then not open URL.
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.
I am not sure if this is possible, but I need to grab all of the push notification userinfo when the user opens up the App. I can get all of the push notification userinfo when the App is opened or in the background, but not when the App is completely closed. Any way around this? The code below is how I get the userInfo currently.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
id data = [userInfo objectForKey:#"data"];
NSLog(#"data%#",data);
}
Unfortunately, it's not currently possible client side with that method to query old notifications that have occurred while the app was completely closed. See this question: didReceiveRemoteNotification when in background.
A way around it is to keep track of which notifications you send from your server per user. When didReceiveRemoteNotification: is called, you can take that notification and compare it against the server's messages for the current user. If one of them matches, mark it some way on the server. That way, if there are messages sent when your app is backgrounded, you can query for messages that haven't been marked from the server and get all 'missed' notifications.
The method you are implementing cannot handle both cases. See the "Local and Push Notification Programming Guide":
If your app is frontmost, the application:didReceiveRemoteNotification: or application:didReceiveLocalNotification: method is called on its app delegate. If your app is not frontmost or not running, you handle the notifications by checking the options dictionary passed to the application:didFinishLaunchingWithOptions: of your app delegate...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Notifications
NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(userInfo){
//open from notification message
}
return YES;
}
You can add this code to your AppDelegate's applicationWillEnterForeground method:
-(void)applicationWillEnterForeground:(UIApplication *)application {
// this method is called when staring an app that was closed / killed / never run before (after applicationDidFinishLaunchingWithOptions) and every time the app is reopened or change status from background to foreground (ex. returning from a mobile call or after the user switched to other app and then came back)
[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
NSLog(#"AppDelegate-getDeliveredNotificationsWithCompletionHandler there were %lu notifications in notification center", (unsigned long)[notifications count]);
for (UNNotification* notification in notifications) {
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo) {
NSLog(#"Processed a notification in getDeliveredNotificationsWithCompletionHandler, with this info: %#", userInfo);
[self showPushNotificationInAlertController:userInfo]; // this is my method to display the notification in an UIAlertController
}
}
UIApplication.sharedApplication.applicationIconBadgeNumber = 0;
}];
}
}
Remove this line from the method application didFinishLaunchingWithOptions: if you had included it there, because it clears the badge number and also all notifications in notifications center:
UIApplication.sharedApplication.applicationIconBadgeNumber = 0;
This is currently working in iOS 12, hadn't had the chance to test it in earlier versions.
I need to run specific code if a local notification was fired while the application was in the background and has now entered the foreground. One way to do this is to get the badge count, is there a better way?
Check out the docs at http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html
Your App Delegate can detect notifications when the app is in the background
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
NSString *itemName = [notif.userInfo objectForKey:ToDoItemKey]
[viewController displayItem:itemName]; // custom method
application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber-1;
}