How to clear the remote notification in your app? - ios

Is there a way to clear the remote notification from the notification banner when swiping down from the top of the iPhone screen. I tried setting the badge number to zero:
application.applicationIconBadgeNumber = 0
in delegate didFinishLaunchingWithOptions, and didReceiveRemoteNotification, but it did not clear the notifications. Thanks.

In iOS 10, above all solutions are depreciated
'cancelAllLocalNotifications()' was deprecated in iOS 10.0: Use UserNotifications Framework's -[UNUserNotificationCenter removeAllPendingNotificationRequests]
Use the below code to cancel notification and reset Badge count
For iOS 10, Swift 3.0
cancelAllLocalNotifications deprecated from iOS 10.
#available(iOS, introduced: 4.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenter removeAllPendingNotificationRequests]")
open func cancelAllLocalNotifications()
You will have to add this import statement,
import UserNotifications
Get notification center. And perform the operation like below
application.applicationIconBadgeNumber = 0 // For Clear Badge Counts
let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications() // To remove all delivered notifications
center.removeAllPendingNotificationRequests() // To remove all pending notifications which are not delivered yet but scheduled.
If you want to remove single or multiple specific notifications, you can achieve it by below method.
center.removeDeliveredNotifications(withIdentifiers: ["your notification identifier"])
Hope it helps..!!

You need to set the IconBadgeNumber to 0 and cancel the current notifications. I never did in swift but I think the code for it would be as bellow:
application.applicationIconBadgeNumber = 0
application.cancelAllLocalNotifications()
Swift 5
UNUserNotificationCenter.current().removeAllDeliveredNotifications()

I have to increment then decrement badge count in order for it to work:
application.applicationIconBadgeNumber = 1
application.applicationIconBadgeNumber = 0
application.cancelAllLocalNotifications()

Swift 3
In your AppDelegate.swift file under didFinishLaunchingWithOptions add:
application.applicationIconBadgeNumber = 0
On the launch of your app this will remove the iOS badge (red circle at the top right corner of the app icon).

any one looking for swift 4 and above code
application.applicationIconBadgeNumber = 0
UNUserNotificationCenter.current().removeAllDeliveredNotifications()

This for scenario when the app is forcefully terminated by the user :
First of all send nonzero badge when you want to send Birthday reminders notifications to the users via push notifications , For example :
{
"aps": {
"alert": {
"title": "Hey! Urgent Reminder",
"body": "Do not forget my wife SURPRISE BIRTHDAY PARTY"
},
"badge": 1
}
}
After that , When there is no need of showing notifications in the device , you can send silent notification with zero badge that will clear badge and notifications even if app is forcefully terminated by the user but didReceiveRemoteNotification will not called because app is terminated.
payload for silent push notification :
{
"aps" : {
"content-available" : 1,
"badge" : 0,
"Priority" : 10
}
}
After send that payload will automatically clear badge and delete push notification from Notification Center.
Not. If badge was zero before sending silent notification , will not clear notifications.
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html

In Nov, 2019 below is the working solution for me with Swift 4. First you have to check the device version to clear all notifications but do not need to check to reset badge count.
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?  ) -> Bool {
//--------
application.applicationIconBadgeNumber = 0
  if #available(iOS 10.0, *) {       
let center = UNUserNotificationCenter.current() 
center.removeAllDeliveredNotifications() 
center.removeAllPendingNotificationRequests()   
} else {       
application.cancelAllLocalNotifications()    
}        
//------
}

Swift 4 & 5
import UserNotifications
...
...
...
UNUserNotificationCenter.current().removeAllDeliveredNotifications()

Related

didReceiveRemoteNotification: is not called after notification arrives and app is in background/suspended mode

Within AppDelegate I simply update applicationIconBadgeNumber:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
application.applicationIconBadgeNumber += 1
}
Everything works as expected when the app is connected to Xcode and is in debugger mode. But just after I plug it out from Xcode, notification arrives but badge is not updated. App is in background mode.
Why? What is wrong with my approach? Please, give me an advice🏆
Push notification are handled by iOS and not your app you can't change the application badge on receiving a push notification.
You can send the badge number in the payload of the push notification,
Payload could look like this:
{
"aps" : {
"alert" : "Notification REceived",
"badge" : 1
}
}
I found this post very helpful for managing notifications in the background, basically you have to use the call with completion handler.
didReceiveRemoteNotification when in background
I think the best way to manage badge count is on the server.
A push notification will automatically update the badge on the app icon.
Payload formate.
{
"aps" : {
"alert" : "Weather report udapted",
"badge" : 5
}
}
Your messagingManager is an optional. You should check, that it isn't nil. If it is nil, the appDidReciveMessage() function would not be triggered

How to reset the Badge app icon number?

I integrated the Push Notification to the CloudKit so that every change in the iCloud will pop up a notification on my iPhone and the badge app icon number will add one correspondingly. However, when I used the code:
application.applicationIconBadgeNumber = 0
to reset that number in the applicationDidBecomeActive(_ application: UIApplication), I noticed that the badge app icon number truly disappeared but if another new notification came again, the number won't start from one again as supposed but just add one to the original total number before the reset. Therefore the number is getting bigger and bigger. I wonder how to solve this problem?
The problem is your apns payload, it contains badge count more than 1, you need to reset the payload as well.
When you set application.applicationIconBadgeNumber = 0 it just resets the badge count locally, not in the server.
Solution would be reset the badge count for the user in the server too.
Update: Apns Payload
{
"aps" : {
"alert" : {
"title" : "Push",
"body" : "Hello User"
},
"badge" : 5
}
}
The app shows the badge count same as in the apns payload above, you need to reset the badge value in the payload above from server.
Hope it helps.
Cheers.
I find that I should not only set the application side like:
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
but I should also set the iCloud side in CKContainer. Therefore, the complete code is like below:
let operation = CKModifyBadgeOperation(badgeValue: 0)
operation.modifyBadgeCompletionBlock = {(error) in
if let error = error{
print("\(error)")
return
}
application.applicationIconBadgeNumber = 0
}
CKContainer.default().add(operation)

How do you replace one push notification with another on the receiving device?

I'm trying to replicate how WhatsApp signals the callee's device about an incoming call when the caller starts a call to a user who has this WhatsApp closed. According to the lock screen, the call receiver's device seems to be repeatedly receiving push notification with an interval of approximately 1 second, saying "Call from UserName". But most notably, the notifications do not pile up. It appears that every notification about an incoming call is replaced by the next such notification. And when the caller drops the call, the last incoming-call notification on the callee end is replaced by "Missed call" notification.
How can I achieve push notification replacement/deletion in this way?
You can use the "apns-collapse-id ". it will replace the Notification contents with the same id
https://developer.apple.com/documentation/usernotifications/unnotificationrequest/1649634-identifier
https://medium.com/the-guardian-mobile-innovation-lab/how-to-replace-the-content-of-an-ios-notification-2d8d93766446
WhatsApp uses silent notifications to trigger the display of local notifications. Local notifications can be replaced by the app. This was the last time I reversed engineered their process. They probably use Push Kit messages now, as they are a VoIP app.
Whatsapp, skype or any other VOIP related app uses push kit.
Use content-available = 1 in payload to make it silent push notification.
Silent push notification will invoke your app in background even if your app is in kill state ( Terminated state ), so it will allow you to schedule local notification.
Once you have payload for incoming call schedule local notification
Once you get payload for missed call, cancel incoming call local notification and schedule missed call local notification
Note - Incoming or missed call local notification object, always keeps in NSUserDefault to ensure its availability to cancel even if you restart your device.
Payload related details you can keep in localnotification.userInfo
Pushkit code
import UIKit
import PushKit
class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate{
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
self. PushKitRegistration()
return true
}
//MARK: - PushKitRegistration
func PushKitRegistration()
{
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
if #available(iOS 8.0, *) {
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
} else {
// Fallback on earlier versions
}
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
print(hexString)
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
// As per payload schedule local notification / cancel local notification
}
}
Kind of pushkit payload
{
"aps": {
"content-available": 1,
"screen": "IncomingCall",
"alertTitle": "Mr ...",
"alertBody": "Call from ...",
"category": "INCOMINGCALL_CATEGORY",
"data": "Any specific data you want to pass"
}
}

CLCircularRegion and wake up app

In application we have mechanism like native Reminder app in iOS with firing notifications when user enter or exit in some region.
But two devices behave differently (5 and 5s) in same time. All devices have enable notifications, and allow use locations.
Two devices have a some "travel" and in the route created 10 points. First device (5) when came to finish received only 6 notifications, (5s) don't receive any notification.
But my question is how I can know when my app is restart in background or continue working. Because, all log in app I redirect into a file, and after download container and analyze what happened in app in travel time.
I noticed app restart in same times when device is enter to region and my log marks fired in the file but notifications don't receive. This is happended when app try to get some information from web service in didFinishLaunchingWithOptions
And maybe this is problem. How to know distinguish restart app or continue working. Thx.
Are you checking UIApplicationLaunchOptionsLocationKey in didFinishLaunchingWithOptions similar to (sorry, Swift is what I have now):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsLocationKey] != nil {
// app was launched in response to incoming location event
}
}
Additionally, if you're not already doing this you may need to create notifications differently if app is in background:
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
}
else {
// Otherwise present a local notification:
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}

Update badge counter in Swift

With following code I get (2) in the badge icon immediately after app compiling:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.badge = 2
installation.saveInBackground()
}
I did try the next variant: Initialized a new var badgeCount = 0 and later:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
badgeCount++
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.badge = badgeCount
installation.saveInBackground()
}
But when I get new notifications it doesn't update to +1. Is anyone know how to fix it?
Whenever code is compiled it shows the badge icon which is previously store in your app. If you don't set the badge icon = 0 in your app it will show the badge icon number in your app every time you compile it or enter in background state.
Now for your problem, use badge icon as
var badgeCount = 0
UIApplication.sharedApplication().applicationIconBadgeNumber = ++badgeCount
Also whenever you are done with your task make badge icon as 0 otherwise it will show a badge icon in your app
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
It won't update the badge number with this method unless the app is actually open. If you want to update the badge number upon receiving a notification then you need to set the Badge property of the json push notification to the desired number.
If you, if you are sending a normal message (not using json) there is a toggle to increment the badge number, just tick that. If you're using Json then use this:
{
"aps": {
"alert": "Test Push Notification",
"sound": "yourSound.aiff",
"Badge": "desiredNumber"
}
}
Please note, if you do not wish to send this from the server, you can also send it from one device to another utilising Parse's client push, go into your settings in the app on Parse.com and enable "client push", you can then send the above Json to another user's device.
In Swift 5, you can update de application's badge whenever you want, using this code:
UIApplication.shared.applicationIconBadgeNumber = 0 // YOUR NUMBER DESIRED
I have worked on similar scenario and the final solution I found to increment and reset the badge numbers.
Increment Badge number
I always save the badge number count in the memory (NSUserDefaults)
Every time i have to set the notification, I get the current badge number increment that and set that number on .applicationIconBadgeNumber and update the count in memory.
Reset Badge Number
In my case, I have to reset all the badge count once the application is opened. So I have set UIApplication.sharedApplication().applicationIconBadgeNumber = 0 in didFinishLaunchingWithOptions of AppDelegate. Also I reset the count in the memory.
None of these answers are valid anymore.
You need to be looking at your Push code, not your AppDelegate
From the Parse docs:
badge: (iOS/OS X only)
the value indicated in the top right corner of the app icon.
This can be set to a value or to Increment in order to increment the current value by 1.

Resources