Search code examples
swiftflutterpush-notificationfirebase-cloud-messagingnotification-service-extension

Flutter and custom iOS Notification Service Extension


I'm adding a custom Notification Service Extension to my flutter app in order to preprocess the notifications (generated from Firebase Cloud Messaging). It doesn't work, not showing at all, the test notifications do work.

I added the extension using xCode briefly on MacInACloud as I'm on windows. This created a new folder, same level as Runner and Flutter. The service file is the following :

import UserNotifications

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Modify the notification content here...
            bestAttemptContent.title = "modified !"
            
            contentHandler(bestAttemptContent)
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

}

Here's the App Delegate file I modified according to this thread I found (Seems it's using outdated API syntax) : Flutter: How to display rich notifications on ios using flutter_messaging plugin?

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
     if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

And here's my JSON request to FCM :

const payload = {
      "token":"evGbKFWA10fFoD2rsTUVOX:APA91bHfOZDkkcim2SjHB1-H5ldZu37OsE3G91s4xRYkbp4vK3PUodvNkzLurAONzxI5NUjf5tzmokfGUBu9avT4y_Uz3L6DpKJ_pMR43knNVctFAobtQupcdy_P_H58q1EtRU02TZ8D",
      "notification":{
        "title":"Secret Message !",
        "body" : "Nothing",
      },
      
      "content-available":0,
      "apns":{
        "headers":{
          "apns-priority":10,
        },
        "payload": {
          "aps" : {
            "category" : "SECRET",
            "mutable-content" : 1,
            "alert" : {
              "title" : "Secret Message!",
                "body"  : "(Encrypted)"
            },
          },
          "ENCRYPTED_DATA" : "Salted__·öîQÊ$UDì_¶Ù∞èΩ^¬%gq∞NÿÒQùw"
        },
      }
  };

The aps payload part is taken from the documentation and follows the required rules: https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications

I'm sure plenty of people have managed to implement this functionality in Flutter before, I just never coded in swift so I hope someone here can point out the reason this doesn't work..

Thanks

PS : I know the flutter documentation shows a way to integrate this extension to their library, but it's only in order to show images. I need something more customizable for my usage. Also since I'm not integrating it in any library I didn't update the Pod file (which I don't have on my windows version)...Hope this makes sense...


Solution

    1. FCM doesn't accept some numbers as is in the JSON and they should be put into quotations marks. Yet the numbers in the APNS for badge or mutable-content should not have quotation marks.

    2. When I created the extension on Xcode, the target OS was automatically set to iOS 16, since my test device is not up to date, it couldn't work...

    I also added the App groups capability since it was mentioned in a few tutorials, but I'm not sure this is relevant and couldn't work without it.