How to add different actions depending on the category defined in incoming remote notification payload? Swift UPDATED

时光怂恿深爱的人放手 提交于 2021-01-28 07:51:10

问题


I'm implementing push notifications in my two related apps and so far I'm able to send a notifications, device to device, and to a topic. On receiving it, notification displays the image at url sent with the payload. My goal is to add actions to the topic notifications, and they would be different for each topic. Ej. actions for "shop-promotions" topic notifications (namely "buy") would be different from "news" topic notification ( namely "play"). So I thought to send a "category" parameter in the remote notification's payload and use that to differentiate between different incoming notifications and display the correct set of actions. Is it possible to define actions in NotificationExtension.swift didReceive or is mandatory to also use a custom UI to display actions? In https://www.pluralsight.com/guides/creating-ios-rich-push-notifications is shown as possible but I'm not succeeding at it.

I'm declaring them as :

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {

        print("NotificationService: dide receive called")
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)


        if let bestAttemptContent = bestAttemptContent {
            if let urlString = bestAttemptContent.userInfo["attachment-url"] as? String,
                let data = NSData(contentsOf: URL(string:urlString)!) as Data? {
                let path = NSTemporaryDirectory() + "attachment"
                _ = FileManager.default.createFile(atPath: path, contents: data, attributes: nil)

                do {
                    let file = URL(fileURLWithPath: path)
                    let attachment = try UNNotificationAttachment(identifier: "attachment", url: file,options:[UNNotificationAttachmentOptionsTypeHintKey : "public.jpeg"])
                    bestAttemptContent.attachments = [attachment]

                } catch {
                    print(error)

                }

                // Actions
                if let category = bestAttemptContent.userInfo["category"] as? String {

                    if category == "shop-promotions" {
                        let buy = UNNotificationAction(identifier: "buy", title: "Buy", options: [])
                        let close = UNNotificationAction(identifier: "close", title: "Close", options: [])

                        let category = UNNotificationCategory(identifier: "shop-promotions", actions: [buy,close], intentIdentifiers: ["buy","close"], options: [])
                        UNUserNotificationCenter.current().setNotificationCategories([category])
                    }
                }

            } // else {
            //                if let contentHandler: ((UNNotificationContent) -> Void) =
            //                    self.notificationContentHandler,
            //                    let content: UNNotificationContent = self.notificationContent {
            //                    contentHandler(content)  }
    

            let buy = UNNotificationAction(identifier: "buy", title: "Buy", options: [])
            let close = UNNotificationAction(identifier: "close", title: "Close", options: [])

            let category = UNNotificationCategory(identifier: "shop-promotions", actions: [buy,close], intentIdentifiers: [], options: [])
            UNUserNotificationCenter.current().setNotificationCategories([category])


            contentHandler(bestAttemptContent)
        }

and this is the dictionary sent for the notification:

let postParams: [String : Any] = [
            "to": topic,
            "notification": [
                //                    "badge" : 1, sendig the badge number, will cause aglitch
                "body": body,
                "title": title,
                "subtitle": subtitle,
                "text": "some text",
                "sound" : true, // or specify audio name to play
                "priority": "high",
                "content_available": true,
                "mutable_content": true,
                "category": "shop-promotions"
            ],
            "data" : [
                "attachment-url": dataUrl,
//                "media_type":"image",
                "productId": productId,
                "price": price
            ]
        ]

UPDATES:

  1. Changed the categories declarations putting them in a static function that I call in didFinishLaunchingWithOptionsafter checking for notification permission and didRegisterForRemoteNotificationsWithDeviceTokenafter getting the token.
  2. Set NotificationService's info.plist without any UNNotificationExtensionCategoryas I saw that that's in NotificationContent's info.plist.
  3. Tried different Target Membership settings for both NotificationService.swift and info.plist. What's the right configuration?

Still in the same situation of only the image showing with the notification.

Can you see what's missing to set up correctly?

The actions function is this:

static func configurePushCategories() {
        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) { (granted:Bool, error:Error?) in
                if error != nil {
                    print(error?.localizedDescription as Any)
                }
                if granted {
                    print("Permission granted")
                } else {
                    print("Permission not granted")
                }
            }

            //  actions

            let buy = UNNotificationAction(identifier: "buy", title: "Buy", options: [.foreground])
            let play = UNNotificationAction(identifier: "play", title: "Play", options: [.foreground])
            let close = UNNotificationAction(identifier: "close", title: "Close", options: [.foreground])

//            let shopPromotionsCategory = UNNotificationCategory(identifier: "shop-promotions", actions: [buy,close], intentIdentifiers: ["buy","close"], options: [])
//            let fixItPromotionsCategory = UNNotificationCategory(identifier: "fix-it-promotions", actions: [buy,close], intentIdentifiers: ["buy","close"], options: [])
//            let cityFixItNewsCategory  = UNNotificationCategory(identifier: "city-fix-it-news", actions: [play,close], intentIdentifiers: ["play","close"], options: [])
//            let countryFixItNewsCategory = UNNotificationCategory(identifier: "country-fix-it-news", actions: [play,close], intentIdentifiers: ["play","close"], options: [])

            let shopPromotionsCategory = UNNotificationCategory(identifier: "shop-promotions", actions: [buy,close], intentIdentifiers: [], options: [])

            let fixItPromotionsCategory = UNNotificationCategory(identifier: "fix-it-promotions", actions: [buy,close], intentIdentifiers: [], options: [])

            let cityFixItNewsCategory  = UNNotificationCategory(identifier: "city-fix-it-news", actions: [play,close], intentIdentifiers: [], options: [])

            let countryFixItNewsCategory = UNNotificationCategory(identifier: "country-fix-it-news", actions: [play,close], intentIdentifiers: [], options: [])

            UNUserNotificationCenter.current().setNotificationCategories([shopPromotionsCategory,fixItPromotionsCategory, cityFixItNewsCategory, countryFixItNewsCategory])
        } else {
            // Fallback on earlier versions
        }
    }

回答1:


Apple documentation states:

When your push server wants to send a notification to a user, it can add a category key with an appropriate value to the notification’s payload. When iOS sees a push notification with a category key, it looks up the categories that were registered by the app. If iOS finds a match, it displays the corresponding actions with the notification.

#Notification Payload:

 {
    "aps": {
        "category": "MEETING_INVITATION",
        "alert": {
            "title": "Weekly Staff Meeting",
            "body": "Every Tuesday at 2 pm"
        }
    },
    "MEETING_ID": "123456789",
    "USER_ID": "ABCD1234"
}

To support actionable notifications, you must:

  • Declare one or more notification categories at launch time from your iOS app.

  • Assign appropriate actions to your notification categories.

  • Handle all actions that you register.

  • Assign category identifiers to notification payloads when generating notifications.




回答2:


Finally found the reason for actions not showing after all the changes. In the dictionary "category": "someValue" needs to be declared as "click_action":"someValue"..as it goes to Firebase.. not sure I agree with that choice..maybe it's just to spice up what would have been an otherwise boring existence as developers..thank you Firebase.. Sarcasm apart thank you very much for the help on this one too.



来源:https://stackoverflow.com/questions/56579999/how-to-add-different-actions-depending-on-the-category-defined-in-incoming-remot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!