10
votes

I'm using FCM for cloud messaging. I want to add app badge when I receive a push notification from the server in background and foreground app states. What I'm missing? Main problem is adding/updating/removing app badge according to push notification, I can receive and handle push messages .I'm 3 days on this problem. Help me, please !? * Badge numbers changes according to inside contents, like if new email messages received to gmail app, badge number changes to unreaded message count in both background and foreground app states.

using XCode 9.2, swift 3.2, iOS 11.6

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    FirebaseApp.configure()
    var fcmtoken: String = ""

    if #available(iOS 10.0, *) {
        // For iOS 10 display notification (sent via APNS)
        UNUserNotificationCenter.current().delegate = self

        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in })
    } else {
        let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
    }

    application.registerForRemoteNotifications()

    if let token = Messaging.messaging().fcmToken {
        fcmtoken = token
        print("FCM token: \(fcmtoken)")
    } else {
        print("FCM token: \(fcmtoken) == no FCM token")
    }

    return true
}

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
    print("Firebase registration token: \(fcmToken)")

    Messaging.messaging().subscribe(toTopic: "all")
    print("subscribed to all topic in didReceiveRegistrationToken")

    // TODO: If necessary send token to application server.
    // Note: This callback is fired at each app startup and whenever a new token is generated.
}


func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
    Messaging.messaging().subscribe(toTopic: "all")
    print("subscribed to all topic in notificationSettings")
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {

    print("userInfo -- \(userInfo)")

}

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    let userInfo = response.notification.request.content.userInfo
    print("user info in didReceive response -- \(userInfo)")

}


@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

    print("called to foreground app")
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    Messaging.messaging().subscribe(toTopic: "all")
    print("subscribed to all topic in didRegisterForRemoteNotificationsWithDeviceToken")
}
1

1 Answers

16
votes

Payloads are Your Content:

Much of what we just did replaces the trigger in a local notification. Content for a notification is found in the payload. Going back to the testing platform, you’ll find this:

{"aps":{"alert":"Enter your message","badge":1,"sound":"default"}}

Ideally your JSON file should look like this. You only have 4K for your payload so wasting it on spaces is frowned on. When sending payloads avoid whitespace. However, they are hard to read this way. It looks better like this:

{
 "aps":{
        "alert":"Enter your message",
        "badge":1,
        "sound":"default"
 }
}

The aps is a JSON dictionary with entries that describe your content. The alert entry is can be a string like it is here, or a dictionary describing the content of the alert that shows on your device. The badge give the number to show on the badge icon. The sound plays the default sound. You can modify this payload to change the content displayed in the alert. As the alert can be both a dictionary or a string you can add more to it. Change the payload to this:

{
 "aps":{
        "alert":{
                "title":"Push Pizza Co.",
                "body":"Your pizza is ready!"
         },
            "badge":42,
            "sound":"default"
 }
}

This will add a title and a message about your pizza being ready. It will also change the badge to 42

{"aps":{"alert":{"title":"Push Pizza Co.","body":"Your pizza is ready!"},"badge":42,"sound":"default"}}

enter image description here

The notification appears with the title and body. The badge appears with the number 42.

However, you can also change it while your app is active. You will need permission from the user by registering the UserNotificationType. Once you get permission, you can change it to whatever number you wish.

  application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert |
    UIUserNotificationType.Badge, categories: nil
    ))

application.applicationIconBadgeNumber = 5

You can also do like:

  let badgeCount: Int = 10
    let application = UIApplication.shared
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
        // Enable or disable features based on authorization.
    }
    application.registerForRemoteNotifications()
    application.applicationIconBadgeNumber = badgeCount

Result:

enter image description here

Notes: Please check app permission for badge like : enter image description here

Reference: https://makeapppie.com/2017/01/03/basic-push-notifications-in-ios-10-and-swift/