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?
Related
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 implement local notification in my application. I don't know how to do properly, below code I am using for new data arrival process, here after how to implement Notification process and I need notifications during both foreground and background modes.
Below I had successfully background fetching process for new data arrival checking method
// Value matching and trying to get new data
[live_array removeObjectsInArray:stored_array];
// if you require result as a string
NSString *result = [stored_array componentsJoinedByString:#","];
NSLog(#"New Data: %#", result); // objects as string:
Above code finally giving some string value...Once the value came I want to show the notification. Everything I am doing is in the App Delegate.
1) When the app is closed, schedule a local notification that will fire in 24 hours
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [[NSDate date] dateByAddingTimeInterval:60*60*24];
notification.alertBody = #"24 hours passed since last visit :(";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
2) if the app is opened (before the local notification fires), cancel the local notification
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
//For local Notification
first thing we need to do is register the notifications.
// New for iOS 8 - Register the notifications
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
Now let’s create the notification itself
UILocalNotification *notification = [[UILocalNotification alloc] init];
if (notification)
{
notification.fireDate = _datePicker.date;
NSDate *fireTime = [[NSDate date] addTimeInterval:10]; // adds 10 secs
notification.fireDate = fireTime;
notification.alertBody = #"Alert!";
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.applicationIconBadgeNumber = 1;
notification.soundName = UILocalNotificationDefaultSoundName;
switch (_frequencySegmentedControl.selectedSegmentIndex) {
case 0:
notification.repeatInterval = NSCalendarUnitDay;
break;
case 1:
notification.repeatInterval = NSCalendarUnitWeekOfYear;
break;
case 2:
notification.repeatInterval = NSCalendarUnitYear;
break;
default:
notification.repeatInterval = 0;
break;
}
notification.alertBody = _customMessage.text;
Once we have the notification created we need to schedule it with the app.
// this will schedule the notification to fire at the fire date
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
// this will fire the notification right away, it will still also fire at the date we set
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
If we leave things the way they are now a notification will only appear on screen if the app is in the background. In order to display something when the app is in the foreground and a notification fires we need to implement a method in the app delegate.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Notification Received" message:notification.alertBody delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
}
We added a icon badge to our app, and this icon badge will only display when the app is in the background. Generally you want to dismiss the icon once a user has opened the app and seen the notification. We’ll need to handle this in the app delegate as well.
These two methods will take care of it.
- (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.
NSLog(#"%s", __PRETTY_FUNCTION__);
application.applicationIconBadgeNumber = 0;
}
- (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.
NSLog(#"%s", __PRETTY_FUNCTION__);
application.applicationIconBadgeNumber = 0;
}
iOS 10 by Apple document:
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:#"Hello!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:#"Hello_message_body"
arguments:nil];
content.sound = [UNNotificationSound defaultSound];
// Deliver the notification in five seconds.
UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:5 repeats:NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:#"FiveSecond"
content:content trigger:trigger];
// Schedule the notification.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:nil];
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.
I am developing iPhone App Using PJSIP. When i enters background mode,if i receive any call.
I am displaying UILocalNotification alert as:
UILocalNotification *notification = [[UILocalNotification alloc] init];
NSString *alertBody = [NSString stringWithFormat:#"NEW VOIP CALL"];
notification.alertBody =alertBody;
notification.alertAction = #"Answer";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
But this alert dismiss after some 4 or 5 seconds.
how to make it repeat for some more time?
The best way in your circumstances is to specify a sound to play - this can be up to 30 seconds long. This seems to keep the notification displayed for the length of the sound:
UILocalNotification *notification =[[UILocalNotification alloc] init];
NSString *alertBody = [NSString stringWithFormat:#"NEW VOIP CALL"];
notification.alertBody =alertBody;
notification.alertAction = #"Answer";
notification.soundName = #"56 Alarm Bell.mp3";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
Solution 1:You need to Execute UIlaocationNotification Using Timer.
Solution 2: You Start Execute Notification when finish Previous notification.
I am trying to run some function every n-minutes when app is not running.
I thing local notification is suitable for that, but I have one problem.
If I set local notification as :
-(void)notification{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = [[NSDate date] dateByAddingTimeInterval:15];
//localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = #"marko";
// Set the action button
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:#"someValue" forKey:#"someKey"];
localNotif.userInfo = infoDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
The notification is fired every time and then do:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
NSLog(#"Recieved Notification %#",notif);
}
What I would want is to after 15s first fire some function and if function return YES then play sound and put badge on it.
How to do that?
If the application is foremost and visible when the system delivers the notification, no alert is shown, no icon is badged, and no sound is played. However, the application:didReceiveLocalNotification: is called if the application delegate implements it.
Make sure you are testing in device.