How to remove badge but not remove all notifications? - ios

If the user has alert style set to Banners. They can receive more than 1 notification without them being prompted to clear it.
I saw same apps, If the click on the latest one & it opens the App, only clear just this one notification, and remove badge;
If I use
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
It will clear all notifications that have received.
So how to remove badge but not remove all notifications?

Here is another sample should working for iOS 11(code in Swift 4.1):
if #available(iOS 11.0, *) {
let content = UNMutableNotificationContent()
content.badge = -1
let request = UNNotificationRequest(identifier: "clearBadge", content: content, trigger: nil)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
} else {
UIApplication.shared.applicationIconBadgeNumber = -1
}

OK, I find the answer in this
add new notification which badge is -1.
- (void)applicationDidEnterBackground:(UIApplication *)application {
if (iOS11) {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.badge = #(-1);
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"clearBadge" content:content trigger:nil];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
} else {
UILocalNotification *clearEpisodeNotification = [[UILocalNotification alloc] init];
clearEpisodeNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
clearEpisodeNotification.timeZone = [NSTimeZone defaultTimeZone];
clearEpisodeNotification.applicationIconBadgeNumber = -1;
[[UIApplication sharedApplication] scheduleLocalNotification:clearEpisodeNotification];
}
}
Then the badge will be removed,but other notifications not.

Related

How to display FCM 'data' message received using firebase-cpp-sdk on iOS?

I need to display a notification when my app is in background or killed. I have no problem to display FCM 'notification' message on iOS using firebase-cpp-sdk, I tried quickstart-cpp/messaging/testapp and it just worked. But when 'data' message is received when app is in background or foreground - no notification is displayed, I just see it in the log that message is received.
I use "content_available": true in message as suggested by many answers. This helps to actually receive the 'data' message, as I can see in the log, but the message is not displayed.
I tried legacy HTTP and HTTP v1 protocols, the result is the same.
An example of legacy HTTP message is:
{
"data": {
"body": "Entrance door Intrusion at 2 Jun 2020 01:32:08",
"title": "Intrusion"
},
"content_available": true,
"to": "fcm_device_token_here"
}
Do I need to manually create a notification like on Android? Or there are some other ways to do it?
To asnwer my own question - yes, I created a local notification. For that I used qt-notification library since I am using QT, but the code example to show notification is the following (taken from the project):
// create content
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = title.toNSString(); // your title
content.body = caption.toNSString(); // your notification text
content.sound = !sound.isEmpty() ? [UNNotificationSound soundNamed: sound.toNSString()] : [UNNotificationSound defaultSound]; // your sound
// content.sound = [UNNotificationSound criticalSoundNamed: sound.toNSString() withAudioVolume: 1.0]; // For that you need Apple's permission
content.badge = #([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
// create trigger time
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
// unique identifier
NSString* identifierNSString = identifier.toNSString();
// create notification request
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifierNSString
content:content trigger:trigger];
// add request
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = id(m_Delegate);
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(#"Local Notification failed");
}
}];

iOS11: Is it possible to launch notification when device is under guided access?

I have a code that allows the device to run an update. It works perfectly when the ipad is not under guided access for information under iOS11 (and it worked under iOS10 & guided accesss):
- (void)viewDidLoad
{
...
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:#"Update!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:#"Update!"
arguments:nil];
// Configure the trigger for a 7am update.
NSDateComponents* date = [[NSDateComponents alloc] init];
date.hour = 18;
date.minute = 31;
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:date repeats:NO];
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest
requestWithIdentifier:#"update" content:content trigger:trigger];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"%#", error.localizedDescription);
}
}];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
// Update the app interface directly.
NSLog(#"");
// Play a sound.
completionHandler(UNNotificationPresentationOptionSound);
}
I found that Ticket, but no exhaustive explanations to accomplish it:
Is it possible under iOS11 to launch notification on guided access?
Thanks in advance.
It appears this was nothing more than an iOS bug which has been fixed in iOS 11.2.5 beta 4. Please see my own question here for more information.
If you can wait until iOS 11.2.5 is released (which will hopefully be soon according to Apple) the issue should just resolve itself. Otherwise you'll need to investigate something like a sockets system instead.

WatchOS App 4.0: How to schedule a local notification

My application in background or inactive mode then local notification not work. I have never receive local notification on watch.
Update: less then 3 minutes schedule a local notification it's work fine but more then 3 minutes it's not work. so how to resolve this issues?
As per my understanding My code is as follows.
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
// Objective-C
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = [NSString localizedUserNotificationStringForKey:#"Remider!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:#"Your watch is out of range" arguments:nil];
content.sound = [UNNotificationSound defaultSound];
// Time
// 15 min
double timer = 15*60;
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time
repeats:NO];
// Actions
UNNotificationAction *snoozeAction = [UNNotificationAction actionWithIdentifier:#"Track"
title:#"Track" options:UNNotificationActionOptionForeground];
// Objective-C
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:#"UYLReminderCategory"
actions:#[snoozeAction] intentIdentifiers:#[]
options:UNNotificationCategoryOptionCustomDismissAction];
NSSet *categories = [NSSet setWithObject:category];
// Objective-C
[center setNotificationCategories:categories];
// Objective-C
content.categoryIdentifier = #"UYLReminderCategory";
NSString *identifier = [self stringUUID];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
content:content trigger:trigger];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Something went wrong: %#",error);
}
}];
Appreciate if any suggestion or idea.
Make sure your iphone is locked. When it comes to notification, its about preference where to deliver that notification.
Run your watch app on simulator, from iPhone simulator schedule the notification and lock the iPhone simulator screen, keep the watch simulator active, in that case when notification is triggered , it will be delivered on your watch simulator. Same will be the case when you will test on actual devices.
Source Link
And when both iphone and watch is locked, preference is iphone.
UPDATE
Notification on Apple Watch

Scheduling multiple Local Notifications in iOS 10 is not working

I am using UNUsernotification for iOS 10 and Xcode 8 Beta 2
I wrote below code for Local Notification in iOS device:
-(void) localNotificationForiOS10:(NSDate *) _reminderDate{
NSLog(#"_reminderDate %#",_reminderDate);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitTimeZone fromDate:_reminderDate];
NSLog(#"NSDateComponents %#",components);
UNMutableNotificationContent *objNotificationContent = [[UNMutableNotificationContent alloc] init];
objNotificationContent.title = [NSString localizedUserNotificationStringForKey:#"Event Name!" arguments:nil];
objNotificationContent.body = [NSString localizedUserNotificationStringForKey:#"You have event reminder"
arguments:nil];
objNotificationContent.sound = [UNNotificationSound defaultSound];
/// 4. update application icon badge number
objNotificationContent.badge = #([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"firedate"
content:objNotificationContent trigger:trigger];
/// 3. schedule localNotification
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Local Notification succeeded");
}
else {
NSLog(#"Local Notification failed");
}
}];
}
I want to set three different or multiple future dates and want reminder of event on defined dates.
When I used the above code for 3 different time on same date
e.g. (2016-12-29 18:05 ,2016-12-29 18:10, 2016-12-29 18:15) than only last one gave notification.
I register Location notification in AppDelegate file.
application.applicationIconBadgeNumber = 0;
if ([[[UIDevice currentDevice] systemVersion] floatValue] > 10.0f) {
#if XCODE_VERSION_GREATER_THAN_OR_EQUAL_TO_8
/// schedule localNotification, the delegate must be set before the application returns from applicationDidFinishLaunching:.
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
#endif
} else {
UILocalNotification *localNotifacation = [self getLocalNotificationFromLaunchOptions:launchOptions];
if (localNotifacation) {
NSString *title = localNotifacation.alertBody;
NSLog(#"Add Title %#",title);
}
}
I tried my self and I tried it.
I am able to cancel the Local Notification in iOS 10.
here is posted code.
how to cancel a local notification in iphone

How can I remove previously delivered notifications when a new notification arrives with UNUserNotificationCenterDelegate in iOS 10?

This question is about the new UserNotifications framework in iOS 10.
I have an app that schedules a local notification every half hour after the user did a certain action in the app, starting at 1 hour.
To avoid cluttering a user's lock screen or notification center, I only want one notification to show up at a time, so there is only one notification with the most recent, relevant information. My plan to achieve this is to clear all delivered notifications any time a new notification is presented.
It seems this should be possible with the new willPresent method of UNUserNotificationCenterDelegate, but it's not behaving as I would expect.
Here's a function that I call to set up all the notifications, starting at 1 hour after the event in the app, and scheduling a notification every half hour until the last one at 23.5 hours after the event:
func updateNotifications() {
for hour in 1...23 {
scheduleNotification(withOffsetInHours: Double(hour))
scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
}
}
This is the function that actually schedules the notifications based on the mostRecentEventDate, which is a Date set elsewhere:
func scheduleNotification(withOffsetInHours: Double) {
// set up a Date for when the notification should fire
let offsetInSeconds = 60 * 60 * withOffsetInHours
let offsetFireDate = mostRecentEventDate.addingTimeInterval(offsetInSeconds)
// set up the content of the notification
let content = UNMutableNotificationContent()
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default()
content.title = "Attention!"
content.body = "It has been \(withOffsetInHours) hours since the most recent event."
// set up the trigger
let triggerDateComponents = Calendar.current.components([.year, .month, .day, .hour, .minute, .second], from: offsetFireDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDateComponents, repeats: false)
// set up the request
let identifier = "reminder\(withOffsetInHours)"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
// add the request for this notification
UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
if error != nil {
print(error)
}
})
}
In my UNUserNotificationCenterDelegate I have the willPresent method set up like this:
func userNotificationCenter(_: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
print("will present...")
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
withCompletionHandler([.alert,.sound])
}
I know the willPresent function is being called because it prints "will present..." but the existing notifications in the notification center don't get cleared. Does anyone know why this doesn't work? Or if there's a way to get it working the way I want it to?
EDIT: I came up with an alternate approach to achieve the same thing, but it also doesn't seem to work.
My idea here was to use willPresent to silence the incoming scheduled notification while scheduling another notification to arrive immediately (without a trigger). All the notifications being scheduled to arrive immediately have the same identifier, so the existing notification with that identifier should always be replaced, like in the example around 20:00 in this 2016 WWDC talk about the new UserNotifications framework. Here's my updated willPresent method:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
let identifier = willPresent.request.identifier
if identifier != "reminder" {
let offsetInHoursString = identifier.replacingOccurrences(of: "reminder", with: "")
let content = UNMutableNotificationContent()
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default()
content.title = "Attention!"
content.body = "It has been \(offsetInHoursString) hours since the most recent event."
let identifier = "hydrationReminder"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
center.add(request, withCompletionHandler: { (error) in
if error != nil {
print(error)
}
})
withCompletionHandler([])
} else {
withCompletionHandler([.alert,.sound])
}
}
EDIT: I finally realized that willPresent will only be called if the app is in the foreground, as it says right at the top of this page, so neither of these approaches should actually work. I thought willPresent would be called every time a notification was received. Back to the drawing board on this "only the newest, most relevant notification" idea...
UPDATE (July 2018): With the introduction of grouped notifications in iOS 12, updating an older notification (with the goal of reducing notification clutter) seems less relevant. I'd still like to be able to do it to minimize the appearance of clutter, and it seems there should be feature parity between remote push notifications, which can be updated after the fact, and local notifications, which can not be updated later. However, since Apple has introduced grouped notifications, I'd expect its less likely they'd implement the ability to update old local notifications in favor of letting apps just send new ones and having them group together with existing notifications.
You can check this demo。
I think you want to achieve the function is called "update notification".
iOS 10 allow update the notification.All you just do——keep the notifications have the same identifier.
Let's see a demo:
first notification:
NSURL * imageUrl = [[NSBundle mainBundle] URLForResource:#"dog" withExtension:#"png"];
UNNotificationAttachment *imgAtt = [UNNotificationAttachment attachmentWithIdentifier:#"image" URL:imageUrl options:nil error:&error];
NSURL * mp4Url = [[NSBundle mainBundle] URLForResource:#"media" withExtension:#"mp4"];
UNNotificationAttachment *mediaAtt = [UNNotificationAttachment attachmentWithIdentifier:#"image" URL:mp4Url options:nil error:&error];
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
//在通知中心显示的总是第一个多媒体资源
content.attachments = #[imgAtt,mediaAtt];
content.badge = #1;
content.title = #"Wake Up";
content.subtitle = #"First time";
content.body = #"next time。。。 ";
content.categoryIdentifier = #"wakeup";
content.launchImageName = #"dog";
content.sound = [UNNotificationSound defaultSound];
// content.threadIdentifier = #"";
content.userInfo = #{#"first":#"5:00 am",#"second":#"6:00"};
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5.0 repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"com.junglesong.pushtestdemo.wakeup" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
NSLog(#"wake up message has been deliverd!");
}];
update the first notification:
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
content.badge = #1;
content.title = #"Update!dear,wake up";
content.subtitle = #"Update! dear,please";
content.body = #"Update!shall we have breakfast?";
content.categoryIdentifier = #"wakeup";
content.launchImageName = #"dog";
content.sound = [UNNotificationSound defaultSound];
// content.threadIdentifier = #"";
content.userInfo = #{#"first":#"5:00 am",#"second":#"6:00"};
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5.0 repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"com.junglesong.pushtestdemo.wakeup" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
NSLog(#"wake up message has been updated!");
}];
Now, you add two notification.But the system treats them as the same.So there is just only one.And the sencond replaces the first one.In iOS 10,call this update.
The property "identifier" is the id of UNNotificationRequest,which can differentiate notifications.
You can just use removeDeliveredNotifications(withIdentifiers:)

Resources