I'm trying to update the badge value remotely via a push notification.
Everything works fine but when the app is open I get an empty alert (containing my app name and a close button).
I read about silent notifications in apple's documentation but it seems that even with specifying content-available : 1 in the notification payload, the payload must not contain badge for the notification to be silent.
Is updating the badge without receiving an alert possible ?
If you are using a silent push notification, then you cannot include the badge key in the aps dictionary, so you can't update the badge directly with a silent push.
You can include your own keys and values in the aps dictionary and this dictionary is available in the didReceiveRemoteNotification:fetchCompletionHandler UIApplicationDelegate function.
In this function you can extract your own "badge" key from the aps dictionary and use this to update the badge number directly using the UIApplication property [applicationIconBadgeNumber][1]
UIApplication.shared.applicationIconBadgeNumber = someValue
Something like:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let badgeNumberStr = userInfo["myBadge"] as? String {
if let badgeNumber = Int(badgeNumberStr) {
application.applicationIconBadgeNumber = badgeNumber
}
}
}
Related
I'm developing an Swift iOS 14 app that send and recieves push notifications from Firebase Cloud Messaging.
From FCM I send a message with a payload that must be treated by the app, updating an internal SQLite database with the payload data for later, show items in a view.
When the app is in Foreground, I recieved the notification in the didReceiveRemoteNotification method and update the database but when the app is in Background or killed, the notification is recieved but no one method is called to handle the payload and update de database.
I've read many topics about this problem but in none have I come to find a solution.
At the moment I don't want to use an external database to insert the data, and later read the external database, but if there is no other options i will change the app (the reason is that i don't want to store any information out of the user application).
My AppDelegate.swift is the following:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Firebase Auth + APNs
FirebaseApp.configure()
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
application.registerForRemoteNotifications()
Messaging.messaging().delegate = self
return true
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
UserDefaults.standard.set(fcmToken, forKey: UserConstants.MESSAGING_TOKEN)
let dataDict:[String: String] = ["token": fcmToken]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if(userInfo["name"] != nil) {
ContactsService.sharedInstance.addAlert(phoneNumber: userInfo["phone"] as! String, name: userInfo["name"] as! String, isLocalized: Bool(userInfo["isLocalized"] as? String), longitude: (userInfo["longitude"] as! NSString).doubleValue, latitude: (userInfo["latitude"] as! NSString).doubleValue)
}
}
Can someone help me, telling me if it's possible to do in that way or it's necessary to store the data externally to later retrieve it?
Thank you!
There are two types of push notifications, alert notifications and background notifications. Alert notifications allow you to deliver visible alerts that can be interacted with in ways that your app can customize.Background notifications allow your application to fetch data from the background, upon receiving push notifications. Background notification should be used to keep your application up to date, even if the application isn't running. Also as of ios 10(and above)instead of using the didReceiveRemoteNotification method you can use didReceive method for handling the alert notifications.
Now coming back to your question in case of the alert notification the didReceive/didReceiveRemoteNotification method is called when the application is in the foreground or when the user taps on the application. Since, you want to update the database you can use the background notifications instead of the alert notification as it will automatically raise your application even when it is in background and will also call the didReceiveRemoteNotification:fetchCompletionHandler. while sending a background push notification make sure you :
Edit Info.plist and check the "Enable Background Modes" and "Remote notifications" check boxes.
Add "content-available":1 to your push notification payload, otherwise the app won't be woken if it's in the background
The notification’s POST request should contain the apns-push-type header field with a value of background, and the apns-priority field with a value of 5.
For more info please refer :
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
I have used Twilio Chat SDK for my iOS app. The notifications when new message is added to the channel is coming up fine. But it doesn't update the app's notification badge count. I have attached the screenshot for push notification configuration in Twilio Portal.
Also when I ask for user authorization for notification,
the options set are:
let options: UNAuthorizationOptions = [.badge, .sound, .alert]
Your notification payload should look like the following to update app badge count:
{
"aps" : {
"alert" : "You got notificaiton.",
"badge" : 5
}
}
When this payload is received the badge count updates to 5.
Update: As mentioned in the Twilio documentation:
To update badge count on an application icon, you should pass badge count from the Chat Client delegate to the application:
func chatClient(_ client: TwilioChatClient, notificationUpdatedBadgeCount badgeCount: UInt) {
UIApplication.shared.applicationIconBadgeNumber = Int(badgeCount)
}
Note: But, this only works when the App is active. To update the badge count when the App is inactive you need to configure notification payload to the above-mentioned format from via a custom Twilio server, default configuration doesn't allow this.
When the app is inactive you can use this method to append the badge count:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if UIApplication.shared.applicationState != .active {
UIApplication.shared.applicationIconBadgeNumber += 1
}
}
I was wondering if i can send multiple push notifications to users through Firebase, but then intercept them before the user sees them on the device and allow my app to selectively allow notifications.
Is this possible?
If so, which method do I need to use? (either from react-native-firebase or iOS)
You can try to use UNNotificationServiceExtension (available from iOS 10). You need to add an extension to you project (example how to add).
After implement method - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler; in your extension.
It will be called before notification shows to user and you can try to do some action (for example: save some data to local).
Note that it works only with iOS 10 rich notifications (how to implement it with Firebase).
P.S. Hope it help for you!
EDIT:
In Apple documentation write:
Override this method and use it to modify the
UNNotificationContent
object that was delivered with the notification.
UPDATE:
You can try to send from server silent push notification, check it and create local notification to show to user if need it.
FireBase notifications can be handled when an application is in foreground state . Firstly you have change notifications to when in use from Always in both your controller and info.plist.
Once you have set it you can control notifications in your App delegate or viewController.
new
You can send silent notification to users and schedule your Actual notification as local notification
Refer This
old
(In Case of Firebase)
Notifications are only manageable in the case when the app is in foreground.
If the app is in background it can’t be handled as user will receive notification and app will not be notified until notification is tapped.
Send a silent remote notification with "content-available" : 1 and decide if you want to show it to user or not.
{
"aps" = {
"content-available" : 1,
"sound" : ""
};
// add custom key value for message
}
If you want to show it to user, fetch custom key-value pair for message and fire a local notification for user to be shown. It will work in the background as well. UIBackgroundMode needs to enabled for Remote Notifications.
You can send data notifications that will be received both in fore- and background. In iOS they are processed by the delegate method application(_:didReceiveRemoteNotification:fetchCompletionHandler:), after processing you can decide there to create a push for the user or not.
#update
For receiving data message (not push) on iOS lower than 10
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
handleNotification(data: userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
on iOS10
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
handleNotification(data: remoteMessage.appData)
}
And then I just check if custom fields have data I need and use NotificationCenter to create local notification
fileprivate func handleNotification(data: [AnyHashable : Any]) {
guard let topic = data["topic"] as? String else { return }
if data["receiver"] as? String == UserManager.shared.current(Profile.self)?.uuid && topic == "coupons" {
displayNotification(data: data)
}
}
fileprivate func displayNotification(data: [AnyHashable : Any]) {
if #available(iOS 10.0, *) {
let content = UNMutableNotificationContent()
content.title = data["notification_title"] as! String
content.body = data["notification_body"] as! String
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 1, repeats: false)
let request = UNNotificationRequest.init(identifier: data["topic"] as! String, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
} else {
if currentNotification != nil {
UIApplication.shared.cancelLocalNotification(currentNotification!)
}
let notification = UILocalNotification()
notification.fireDate = Date()
notification.category = data["topic"] as? String
notification.alertBody = data["notification_body"] as? String
if #available(iOS 8.2, *) {
notification.alertTitle = data["notification_title"] as? String
}
currentNotification = notification
UIApplication.shared.scheduleLocalNotification(currentNotification!)
}
}
Just remember this works with data notification not push notification, but in Firebase you are able to send both types.
Push notification working properly in app from Java APNS,
But one notification in payload with
{
aps = {
"content-available" = 1;
};
key = value;
key = value;
key = value;
}
This is not working in any state of app in iPhone 7, working in other devices, also check with battery mode.
From sender we see log and check response it's sending, but not received in device.
What was the reason for particular device or state ??
i have searched over web but see almost same content which i m using,
i got data in func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
this function when device receive any kind of push notification.
I've got push notifications going to the application I'm working on, but I can't seem to manage them in the application. If I can't manage the notifications in the application, how else can I reduce the incrementing value of the badge icon for the application app-icon?
You can change badge count in push data, also if you need manage received push notification data, use this function:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
It's a snap to change the badge count from anywhere in the app:
UIApplication.sharedApplication().applicationIconBadgeNumber = 4