I have managed scheduling local notification on ios app and have tested them on static notifications interface on apple watch. But, there is a glitch (maybe not?) with that, static local notification interface is being displayed even when the watch app is still running i.e. on the foreground (iphone app is backgrounded and iphone is locked). Also when watch app is active, iphone app is backgrounded, and iphone is NOT locked, iphone is displaying the notification. This is really weird to me.
I'm scheduling local notification as below:
NSString *textToShow = nil;
NSSet *categories = nil;
textToShow = text;
UIMutableUserNotificationAction *notificationAction1 = [[UIMutableUserNotificationAction alloc] init];
notificationAction1.identifier = #"openWKApp";
notificationAction1.title = localStr(#"View");
notificationAction1.activationMode = UIUserNotificationActivationModeForeground;
notificationAction1.destructive = NO;
notificationAction1.authenticationRequired = NO;
UIMutableUserNotificationCategory *notificationCategory = [[UIMutableUserNotificationCategory alloc] init];
notificationCategory.identifier = #"openWKApp";
[notificationCategory setActions:#[notificationAction1] forContext:UIUserNotificationActionContextDefault];
[notificationCategory setActions:#[notificationAction1] forContext:UIUserNotificationActionContextMinimal];
categories = [NSSet setWithObjects:notificationCategory, nil];
UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:notificationType categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = date;
localNotification.alertBody = #"Notification body";
localNotification.applicationIconBadgeNumber = 1;
localNotification.userInfo = info;
localNotification.category = #"openWKApp";
localNotification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
If anybody has faced the same and fixed or found the way around, please, help!
Ended up canceling notifications on willActivate, and re-scheduling on didDeactivate of watchkit. Still, it's really weird to receive notification when watchkit app is running.
Related
I'm trying to create a custom button that then schedules a local notification. The code I've found on here seems to be outdated. I've looked at the outlines from Apple https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
But I'm still pretty confused. Can anyone post a clean and concise example including which files I put which code? (Including registering) Even just an example of creating any local notification would be helpful, thanks!
In AppDelegate.m, register the types of user interactions the app supports (from iOS 8.0 and later)
UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
Inside the button tapped method you do this:
NSDate * fireDate; // The schedule date time.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"alertText";
localNotification.alertAction = #"buttonTitle";
localNotification.soundName = UILocalNotificationDefaultSoundName;
// Schedule it with the app
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
In AppDelegate.m add this method to handle when a local notification arrives (if necessary):
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)localNotification{
// This method gets called when a local notification arrives
}
I need to clear already displayed local notification from Notification Centre programmatically. Following this link I implemented suggested solution, but the problem is that eventArray from this example always has 0 elements. When I swipe down to display Notification Centre I see 4 notifications that I've created previously. So in this case I expect this array to have 4 elements, but it has 0. Any idea why is this so? I've tried on iOS 8.3 and 9.2.1 and array is 0 on both of them.
iOS has 2 ways of presenting local notifications:
From Notification Center:
You can't swipe away notification from left to right.
You can swipe notification from right to left (deleting single notification from the list).
You can click on the notification, after which your app will start and notification will be removed from Notification Center (handled by iOS system)
From Lock screen:
Available only if you enable this setting from iPhone/iPad settings: http://www.imore.com/how-disable-notification-center-lock-screen-your-iphone-and-ipad
You can swipe notification from left to right (your app will be started, handled by iOS). In this case notification from Notification Center is not deleted (iOS doesn't delete it, and doesn't allow deleting a single notification from code after notification is already presented to the user in Notification Center).
You can swipe notification from right to left (deleting single notification from the list, handled by iOS. Notification Center notification is also deleted, handled by iOS).
You can't click on the notification.
EDIT:
Here is code sample how I did it:
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"1";
localNotification.alertTitle = #"1";
localNotification.userInfo = uniqueDictIdentifier1;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
UILocalNotification *localNotification2 = [[UILocalNotification alloc] init];
localNotification2.alertBody = #"2";
localNotification2.alertTitle = #"2";
localNotification2.userInfo = uniqueDictIdentifier2;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification2];
....
//2 more notifications are created like this
And then there is code for filtering all notifications:
NSArray *eventArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++) {
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
if ([userInfoCurrent isEqualToDictionary:uniqueDictIdentifier1]) {
[[UIApplication sharedApplication] cancelLocalNotification:oneEvent];
break;
}
}
For saving a notification for a unique id
NSDictionary * infoDict = #{ #"alarmUiqueId" : uID,
};
NSLog(#"%#",infoDict);
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitSecond
fromDate:fireDate];
fireDate = [fireDate dateByAddingTimeInterval:-comp.second];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = fireDate;
localNotif.timeZone = [NSTimeZone localTimeZone];
localNotif.alertBody = desString;
localNotif.userInfo = infoDict;
localNotif.repeatInterval = NSCalendarUnitDay;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif]
and for delete a paritcular notification write this code.
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for(UILocalNotification *notification in notificationArray)
{
NSLog(#"%#",[notification.userInfo valueForKey:#"alarmUiqueId"]);
if ([[notification.userInfo valueForKey:#"alarmUiqueId"] isEqualToNumber: health.uniqueId])
{
[[UIApplication sharedApplication] cancelLocalNotification:notification] ;
}
}
My understanding is below:
You can not get the information of already notified LocalNotification with scheduledNotifications.
My resolution is that just keep UILocalNotification instance in your singleton object in your application, and call cancelLocalNotification with the instance when you want to delete from Notification Center.
Is this could be your help ?
I am trying to set up an Apple Watch app (presenting flashcards) which fires a notification when a new question is due. If the iPhone is open but the app is in the background it fires a UIAlert, and clicking the action button ("View") opens the app. If the iPhone is locked the notification fires on the Apple Watch with a short glance-long glance with a button "View Question" which opens the Apple Watch app.
It works, but the UIAlert on the iPhone has an annoying "Options" button which requires you to click "Options" to open another UIAlert with two action buttons ("View" and "View Question"), either of which will open the iPhone app. Here is the relevant code which first cancels all previous notifications (as the app allows you to answer a new question before the timer is finished, at which point the timer is reset). It then sets up a notification to be displayed on the iPhone; and finally sets up a notification for the Apple Watch.
// Cancel previous notifications
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// Set up iPhone notification
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:(int)dateLatency];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger intVal = [prefs integerForKey:#"timeLag"];
localNotification.alertBody = [NSString stringWithFormat:#"%ld-%d", (long)intVal, (int)dateLatency];
localNotification.alertAction = [NSString stringWithFormat:#"View"];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertLaunchImage = nil;
localNotification.category = #"qDue";
localNotification.userInfo = [self createAPNS:#"999"]; // function that constructs userInfo json structure
// Set up apple watch notification
NSMutableSet *categories = [[NSMutableSet alloc] init];
UIMutableUserNotificationAction *viewQuestion = [[UIMutableUserNotificationAction alloc] init];
viewQuestion.title = #"View Question";
viewQuestion.identifier = #"viewQuestion";
viewQuestion.activationMode = UIUserNotificationActivationModeForeground;
viewQuestion.authenticationRequired = false;
UIMutableUserNotificationCategory *questionCategory = [[UIMutableUserNotificationCategory alloc] init];
questionCategory.identifier = #"qDue";
[questionCategory setActions:#[viewQuestion] forContext:UIUserNotificationActionContextDefault];
[categories addObject:questionCategory];
UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationType categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
// Schedule it with the app
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
I can get rid of the "Options" button and the extra UIAlert by deleting the apple watch notification, but then there is no notification on the apple watch.
Can anybody tell me why the "Options" button appears, and how to get rid of it?
I am trying to get a set of user notification actions to display with more than 2 buttons. The notification itself utilises the minimal context when app is in the background and this works fine.
When the notification is called while in the foreground, the application:didReceiveLocalNotification: is called as per the documentation on the UILocalNotification class.
How is an alert with more than two buttons (provided by the default context of the action category) ever displayed?
The code below follows the documentation for using more than 2 buttons but only calls application:didReceiveLocalNotification: when the app is in the foreground:
// Selecting YES activates the app in the foreground
UIMutableUserNotificationAction *actionYes = [ UIMutableUserNotificationAction new ];
actionYes.identifier = #"actionYes";
actionYes.title = #"Yes";
actionYes.activationMode = UIUserNotificationActivationModeForeground;
actionYes.destructive = NO;
actionYes.authenticationRequired = NO;
// Selecting NO activates the app in the background
UIMutableUserNotificationAction *actionNo = [ UIMutableUserNotificationAction new ];
actionNo.identifier = #"actionNo";
actionNo.title = #"No";
actionNo.activationMode = UIUserNotificationActivationModeBackground;
actionNo.destructive = NO;
actionNo.authenticationRequired = NO;
// Selecting NEVER activates the app in the background
UIMutableUserNotificationAction *actionNever = [ UIMutableUserNotificationAction new ];
actionNever.identifier = #"actionNever";
actionNever.title = #"Never";
actionNever.activationMode = UIUserNotificationActivationModeBackground;
actionNever.destructive = YES;
actionNever.authenticationRequired = NO;
UIMutableUserNotificationCategory *actionCategory = [ UIMutableUserNotificationCategory new ];
actionCategory.identifier = #"actionCategory";
[ actionCategory setActions: #[ actionYes, actionNo, actionNever ] forContext: UIUserNotificationActionContextDefault ];
[ actionCategory setActions: #[ actionNo, actionYes ] forContext: UIUserNotificationActionContextMinimal ];
NSSet *categories = [ NSSet setWithObjects: actionCategory, nil] ;
UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [ UIUserNotificationSettings settingsForTypes: notificationType categories: categories ];
// The categories have to be registered for notification settings to the app
[ [ UIApplication sharedApplication ] registerUserNotificationSettings: notificationSettings ];
UILocalNotification *localNotification = [ UILocalNotification new ];
localNotification.fireDate = [ NSDate dateWithTimeIntervalSinceNow: 5.0 ];
localNotification.alertBody = #"Testing user notifications message";
localNotification.category = #"actionCategory"; // Same as category identifier
[ [ UIApplication sharedApplication ] scheduleLocalNotification: localNotification ];
For more than 2 buttons, the user has to select "Alerts" as opposed to "Banners" in the app settings menu. The alert will have an Options button that displays the buttons in a list between Open and Close.
The Alert/Banner options cannot be set programmatically.
If an app is in the foreground all notifications will get sent directly to the app delegate application:didReceiveLocalNotification: without exception; this entails that actions cannot be obtained while the app is in the foreground.
I hope this helps anyone else reading through the Apple documentation.
actually am developing an alarm project,
now i have a doubt on Local notification. how can i identify a particular notification.
we can't even set tag to local notification then how can i differentiate them.
example:
notification:1
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = selectedDate;
localNotification.alertBody = #"you got work";
localNotification.alertAction = #"Snooze";
localNotification.repeatInterval = NSDayCalendarUnit;
localNotification.soundName = UILocalNotificationDefaultSoundName;
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:#"setNotificationForEveryDay", #"key", nil];
localNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
notification:2,
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = another selectedDate;
localNotification.alertBody = #"i got work";
localNotification.alertAction = #"Snooze";
localNotification.repeatInterval = NSDayCalendarUnit;
localNotification.soundName = UILocalNotificationDefaultSoundName;
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:#"setNotificationForEveryDay", #"key", nil];
localNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
now i'm in situation to delete the second notification how can i do it...
please help me..
thanks in advance..
My guess is that use the userInfo for distinguishing the local notifications that would be a better idea but for that you need to set the userInfo of the local notification.
Like you could do something like this
if ([Your_notification_Object.userInfo valueForKey:#"Key 1"]==#"Object 1") {
NSLog(#"This is notification 1");
}
now for your second requirement i.e for the deleting part do you want to delete the notification when it is identified as n1 or n2 then in that case you could modify the above code and add this
if ([Your_notification_Object.userInfo valueForKey:#"Key 1"]==#"Object 1") {
NSLog(#"This is notification 1");
[[UIApplication sharedApplication] cancelLocalNotification:Your_notification_Object];
}
Place the above code as per your convenience