14.3 C
New York
Sunday, October 20, 2024

Firebase Notification Photographs not showing at iOS shopper


I’ve arrange my Ktor server to ship Firebase Distant Notifications, every thing works fantastic besides Photographs not being hooked up with the Notification.

Right here is my code:

AppDelegate.swift

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {

    let gcmMessageIDKey = "gcm.Message_ID"

    //referred to as when app launched
    func software(
        _ software: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        print("AppDelegate App launch referred to as")
        //must generate a debug token and print it to the console
        //seek for "App Verify debug token:" within the console to learn the debug token
#if DEBUG
        let providerFactory = AppCheckDebugProviderFactory()
        AppCheck.setAppCheckProviderFactory(providerFactory)
#endif

        FirebaseApp.configure()

        UNUserNotificationCenter.present().delegate = self

        Messaging.messaging().delegate = self

        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.present().requestAuthorization(
            choices: authOptions,
            completionHandler: { _, _ in }
        )

        //simply registers to acquired notifications, doesn't ask permission
        software.registerForRemoteNotifications()

        //get a app verify token
        AppCheck.appCheck().token(forcingRefresh: true) { token, error in
            if let error = error {
                print("App Verify Error fetching token: (error.localizedDescription)")
                return
            }
            if let token = token  {
                print("App Verify token (String(describing: token.token)) created at (token.expirationDate)")
            }
        }

        //register all of the background duties
        registerBackgroundTasks()
        return true
    }

    //referred to as when registering for distant notifications is profitable
    func software(
        _ software: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Knowledge
    ) {
        print("AppDelegate didRegisterForRemoteNotificationsWithDeviceToken referred to as")
        //this technique units the apns token to the system token which is required to establish the system
        Messaging.messaging().apnsToken = deviceToken
    }

    //referred to as when firebase fcm token recieved
    func messaging(
        _ messaging: Messaging,
        didReceiveRegistrationToken fcmToken: String?
    ) {
        print("AppDelegate Firebase registration token referred to as: (String(describing: fcmToken))")

        let dataDict: [String: String] = ["token": fcmToken ?? ""]
        NotificationCenter.default.submit(
            identify: FirebaseMessaging.Notification.Title("FCMToken"),
            object: nil,
            userInfo: dataDict
        )

        // Word: This callback is fired at every app startup and each time a brand new token is generated.
        if let token = fcmToken {
            // Persist it on native storage
            persistViaUserDefaultsToLocalStorage(token, key: UserDefaultsFileKeys.notificationTokenPreferencesUDKey.rawValue)
            // Add token to ktor
            uploadNotificationToken(token: token, appManager: AppSingleton.occasion)
        }
    }

    //obtain displayed notifications for iOS 10 gadgets.
    //calld when app is in foreground and distant notification acquired
    func userNotificationCenter(
        _ heart: UNUserNotificationCenter,
        willPresent notification: UNNotification
    ) async -> UNNotificationPresentationOptions {
        let userInfo = notification.request.content material.userInfo
        print("AppDelegate userNotificationCenter willPresent referred to as userInfo is (userInfo)")
        return [[.banner, .badge, .sound]]
    }


    //referred to as when notification acquired
    func userNotificationCenter(
        _ heart: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler : @escaping () -> Void
    ) {
        print("userNotificationCenter didReceive referred to as")
        //get the person data
        let userInfo = response.notification.request.content material.userInfo
        //submit the notification for the system to indicate it
        NotificationCenter.default.submit(identify: Basis.Notification.Title("didReceiveRemoteNotification"), object: nil, userInfo: userInfo)
        completionHandler()
        print(userInfo)
    }


    func software(
        _ software: UIApplication,
        didReceiveRemoteNotification userInfo: [AnyHashable : Any],
        fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
    ) {
        // Deal with incoming notifications
        print("App Delegate Obtained distant notification referred to as: (userInfo)")
        completionHandler(.newData)
    }

    //used to deal with google sign up
    func scene(
        _ scene: UIScene,
        openURLContexts URLContexts: Set
    ) {
        guard let url = URLContexts.first?.url else { return }
        GIDSignIn.sharedInstance.deal with(url)
    }

}

I’ve adopted the steps right here to create a Notification Service goal.

NotificationService.swift

class NotificationService: UNNotificationServiceExtension {

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

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

        print("NotificationService didReceive referred to as") //This doesnt get printed when a brand new distant message is acquired in app foreground or background
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content material.mutableCopy() as? UNMutableNotificationContent)

        guard let bestAttemptContent = bestAttemptContent else { return }

        // Verify if the notification payload accommodates a picture URL
        guard let imageURLString = bestAttemptContent.userInfo["image-url"] as? String,
              let imageURL = URL(string: imageURLString) else {
            contentHandler(bestAttemptContent)
            return
        }

        // Obtain and course of the picture
        downloadAndAttachImage(from: imageURL, to: bestAttemptContent) { updatedContent in
            contentHandler(updatedContent)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

    personal func downloadAndAttachImage(from url: URL, to content material: UNMutableNotificationContent, completion: @escaping (UNNotificationContent) -> Void) {
        let process = URLSession.shared.downloadTask(with: url) { localURL, _, error in
            guard let localURL = localURL, error == nil else {
                completion(content material)
                return
            }

            do {
                let attachment = strive UNNotificationAttachment(identifier: "picture", url: localURL, choices: nil)
                content material.attachments = [attachment]
                completion(content material)
            } catch {
                print("Error creating attachment: (error.localizedDescription)")
                completion(content material)
            }
        }
        process.resume()
    }
}

My Notification Service Extension has additionally been added the Push Notification Signing Functionality in XCode.

Right here is how I’m establishing the notification at Ktor through Firebase admin:

val messageBuilder = Message.builder()
messageBuilder.setApnsConfig(
            ApnsConfig.builder()
                .setAps(
                    Aps.builder()
                        .setAlert(
                            ApsAlert.builder()
                                .setTitle(notification.heading?.removeSquareBrackets())
                                .setBody(notification.message.removeSquareBrackets())
                                .construct()
                        )
                        .setSound("default")
                        .setBadge(1)
                        .setCategory(notification.notificationChannelId + notificationChannelIdVersion)
                        .setMutableContent(true)
                        .setContentAvailable(true)
                        .construct()
                )
                .putHeader("apns-priority", "10")
                .setFcmOptions(
                    ApnsFcmOptions.builder()
                        .setImage("https://firebasestorage.googleapis.com/v0/b/jinarya-315507.appspot.com/o/FCMImagespercent2Fzitykach_3d_animation_BB-8_robot_holding_a_chart_containing_a_53875512-7623-4931-9d91-11764eb364f8_0.jpg?alt=media&token=ea2c8a40-4adf-48f1-89f3-4fe82d738724")
                        .construct()
                )
                .putCustomData("image-url", "https://firebasestorage.googleapis.com/v0/b/jinarya-315507.appspot.com/o/FCMImagespercent2Fzitykach_3d_animation_BB-8_robot_holding_a_chart_containing_a_53875512-7623-4931-9d91-11764eb364f8_0.jpg?alt=media&token=ea2c8a40-4adf-48f1-89f3-4fe82d738724")
                .construct()
        )

The difficulty I’m going through right here is that the pictures are usually not getting hooked up to the notification earlier than exhibiting it on the shopper(I’m testing on a Actual Machine), in any other case every thing else works fantastic.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles