I'm adding a video chat to my app and use PushKit to get a pushNotification when the app is in the background. I Can't use the CallKit for video as it mess up the SDK I'm using so I have added a local push notification that fire up from the PushKit delegate method.
I'm wondering how Whatsapp does it with their Video call. For now they are showing a push notification but in a way that I can't recognize. The push is fired up with two vibrations and after two seconds there is a new push that overlaps the first notification and you can feel another two vibrations and so on until you answer. How do they do it as you can't add vibration over and over again and how do they delete the notification and establish a new one in the background as the NSTimer is not working in the background. If I add [[UIApplication sharedApplication] beginBackgroundTaskWithName:expirationHandler:] then I can use the timer for 180 seconds but only if the app was active.
So the real problem is how to add a local notification that can repeat itself few times and also add vibration to it?
For iOS 10 and later.
Use UNUserNotificationCenter:
let notificationContent = UNMutableNotificationContent()
// this sets sound + vibration
notificationContent.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 1,
repeats: false
)
let request = UNNotificationRequest(
identifier: "notification_identifier",
content: notificationContent,
trigger: trigger
)
UNUserNotificationCenter.current().add(request) { _ in }
You can create a notification in the future and when it gets called cancel all the previous ones and reschedule until you're satisfied.
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = body;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.fireDate = [NSDate new]; //<-Set the date here in 10seconds for example
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Then in application didReceiveLocalNotification:(UILocalNotification *)notification:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
application cancelAllLocalNotifications;
}
Related
I want to set a notification that repeats every 14 days(2 week).I am using old notification framework "UILOCAL NOTIFICATION" as i want it to work with only ios 9.
Either you must do as this answer says: Repeating a Local Notification after every 14 days(two weeks)? or you must let your app handle this by scheduling a local notification for the first occurrence, and then when this notification is received by your app, reschedule it for another 14 days.
Yes you can do easly,
Epic: When the user leave the app, we set UINotification and then send it. if the user not enter in 2 days(2*24*60*60), the notification will send end of the 2 days. if you want to send after 14 days, you can change the fireDate time with 14*24*60*60
in AppDelegate :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2*24*60*60];
//[[NSDate date] dateByAddingTimeInterval:5];[NSDate dateWithTimeIntervalSinceNow:24*60*60]
NSLog(#"%#",notification.fireDate);
notification.alertBody = NSLocalizedString(#"NOTIFICATION_MSG", #"Message");
notification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
- (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.
[[UIApplication sharedApplication] cancelAllLocalNotifications];
application.applicationIconBadgeNumber = 0;
}
I have made the ExtensionDelegate my UNUserNotificationCenterDelegate and properly assigned it. I have my watchOS 3 app add a notification request, which triggers
userNotificationCenter:willPresentNotification:withCompletionHandler:
I have implemented the method as follows:
- (void) userNotificationCenter:(UNUserNotificationCenter*)center
willPresentNotification:(UNNotification*)notification
withCompletionHandler:(void(^)(UNNotificationPresentationOptions))completionHandler
{
NSLog(#"ExtensionDelegate: willPresent!");
completionHandler(UNNotificationPresentationOptionAlert);
}
The problem is that nothing happens. I'm debugging in Xcode 8.2 on a device running watchOS 3.1, and though this delegate method is triggered, and I can hit the breakpoint, no alert is shown. My content is as follows:
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = notificationType;
content.subtitle = [NSString stringWithFormat:#"Subtitle: %#", notificationType];
content.body = alertTitle;
content.badge = #1;
content.sound = [UNNotificationSound defaultSound];
content.launchImageName = #"LaunchImage";
content.userInfo = #{
#"notificationType" : notificationType,
#"count" : #(count)
};
content.attachments = #[];
content.categoryIdentifier = notificationType;
where notificationType is the NSString I set on my application's launch as follows:
// Register custom notification types
UNNotificationCategory* cat1 = [UNNotificationCategory categoryWithIdentifier:#"Category1"
actions:#[dismissAction]
intentIdentifiers:#[]
options:UNNotificationCategoryOptionNone];
UNNotificationCategory* cat2 = [UNNotificationCategory categoryWithIdentifier:#"Category2"
actions:#[dismissAction, yesAction]
intentIdentifiers:#[]
options:UNNotificationCategoryOptionNone];
NSSet* categorySet = [NSSet setWithArray:#[cat1, cat2]];
[center setNotificationCategories:categorySet];
Unfortunately, when the notification request is made, willPresentNotification comes and goes, the completionHandler gets called, and then the app just keeps on running in the foreground. No notification alert appears on screen. It doesn't appear in the drag-down dock on the watch face, either. What else do I need to do to have it appear, either on-screen then and there, or into the pull-down dock?
Here is a visual example of what I'd expect to see on top of the app, or flush-top with the the top of the screen,with the app running below it. The banner can be even thinner than shown here:
Simple watchOS Notification
Related question, but for iOS: Displaying a stock iOS notification banner when your app is open and in the foreground?
I have been trying the same thing on the watch and get the same (non-displayed notification) result. One note, in case it helps others, is that we have to ask for the same permission as we return in the completion handler. For example, if we want to show Alert notifications, we have to use the two corresponding values as shown below. As the OP noted, we have to set ourself as the notification center delegate.
(BTW, if I've got any errors here, please point them out - mine is not working yet either).
The following code is in the watchkit extension delegate.
- (void)applicationDidFinishLaunching {
// ...
// Register for, and request permission to send notifications
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// Enable or disable features based on authorization.
NSLog(#"Got auth response: %d", granted);
}];
}
The above is successful only when I have the notification permissions set to "Mirror the iPhone". If I turn that off, my permissions request fails. A different problem, but please check the returned granted value and make sure it's true.
// Foreground notification
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
// The method will be called on the delegate only if the
// application is in the foreground.
NSLog(#"Will present notification: %#", notification);
// The following doesn't present the notification, though.
completionHandler(UNNotificationPresentationOptionAlert);
}
The userNotificationCenter:willPresentNotification:withCompletionHandler method does get called, but I don't see a notification overlay, nor is there one in the notifications list.
In iOS 7, when a user swipes one of my notifications from the lockscreen and is taken to my app, the notification sound keeps playing (unlike iOS 6). Is there any way to programmatically stop that sound when my app launches in iOS 7?
NOTE: see the accepted answer for a shoddy workaround.
I'm pretty sure this is a bug on Apple's end, see devforums.apple.com/message/888091 (thanks Gui13). File a duplicate bug report to get Apple to pay attention to it, as that is how Apple assigns priority to bugs. In the meantime, the following will work but will also clear all of your notifications in the notification center, which of course is a shoddy workaround, but in my case is worth it until this gets fixed:
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 1];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
it doesn't help by using
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 1];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
after entering the app by clicking the notification.
I have solved this problem by sending another empty notification when dealing with the notification with sound:
if (notification.soundName != nil) {
if (IS_IOS7) {
UILocalNotification *emptyNotification = [[UILocalNotification alloc] init];
emptyNotification.timeZone = [NSTimeZone defaultTimeZone];
emptyNotification.fireDate = [NSDate date];
emptyNotification.alertBody = #"";
[[UIApplication sharedApplication] scheduleLocalNotification:emptyNotification];
}
}
For iOS 7, the accepted answer may be the only viable option. For developers who have come here that can support a minimum of iOS 10, this works.
You can remove all notifications from Notification Center by calling
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
This has a very similar affect as the accepted answer: the audio stops playing and all the notifications are removed from Notification Center.
An improved solution is to use
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [String])
This stops the audio for only the given notifications, and removes them from Notification Center.
To get the ids for all the delivered notifications, use
UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
let ids = notifications.map { $0.request.identifier }
}
in my app i schedule some UILocalNotification every time the app is opened, but happen that sometimes the uilocalnotification is not fired and don't notify me,and when happen they don't fired anymore, to fix it i have to reinstall the app on the iPhone, so i'm explain me well, there is a period of time that the notification work and then one day the dont' work anymore and to fix it i have to reinstall it again, so to investigate i have create this method that it's called when the app did become active:
-(void)checkNotification {
for (UILocalNotification *someNotification in [[UIApplication sharedApplication] scheduledLocalNotifications]) {
NSLog(#"%#",someNotification.alertBody);
NSLog(#"%#",someNotification.fireDate);
}
}
and i see that all notification are scheduled and also the date, this is an example:
2012-11-25 18:36:36.532 TestApp[672:907] This is a notification.
2012-11-25 18:36:37.482 TestApp[672:907] 2012-11-27 10:00:00 +0000
so i can't understand why i don't receive notification...any help?
Edit:
i create a notification in this way:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = myNewDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"This is a notification.";
localNotification.soundName = #"smallBell.mp3";
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
You may or may not get the alert message. It depends on whether your app is running and in which state, e.g. active in the foreground, active in the background, or not running at all.
Please see this article for clarification - http://www.thekspace.com/home/component/content/article/62-uilocalnotification-demystified.html
I'm uisng this code to display a movie:
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc]
initWithContentURL:movieURL];
mp.moviePlayer.movieSourceType = MPMovieSourceTypeUnknown;
[self presentMoviePlayerViewControllerAnimated:mp]; [mp.moviePlayer play];
The code is working fine. However when the application goes to the background while playing a movie, when the app comes back in the foreground the movieplayer is not displayed. (I see the view of the controller that called presentMoviePlayerViewControllerAnimated:mp
Is it possible when entering the foregound to resume the movie that was playing before the app went to the background?
Have you set the UIBackgroundmode to audio and also there has been problem with playing the video after app enters foreground .Refer this Tutorial on MPMoviePlayerViewController Also you can try using MPMoviePlayerViewController which has options for implementing various notifications .
you can implement notification techniques to handle it. Add a notification in the class where movie player is playing and associate with it a selector. When app goes to background then in the delegate method
- (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.
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = 0;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}
write this code.Actually when app goes background it pauses the MPMoviePlayerController so when it is coming to foreground you post the notification which call the method in class where movie controller is implemented and play it again in this method.
-(void)playIntroAnimationAgain
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:NOTIFICATION_PlayAgain_Player object:nil];
[self.moviePlayerController play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playIntroAnimationAgain)name:NOTIFICATION_PlayAgain_Player object:nil];
}
It solved my problem.