Flutter

Flutter Image Push Notification 설정 및 오류 정리

smileDeveloper 2024. 1. 24. 14:12
반응형
SMALL

이 포스팅을 따라하기 전엔 FCM 및 APNS 설정이 선행되어야 합니다.

Push Notification에서 이미지와 같이 보내기 위해선 FCM API Payload에 image 데이터가 필요합니다. 안드로이드에서는 바로 작동하지만 IOS에서는 따로 설정을 해줘야 합니다. Image Push Notification을 설정하는 글이 잘 설명되어 있었지만 글을 따라하면서 생긴 오류들을 어떻게 해결했는지 적어보겠습니다. 

 

Image Push Notification(Advanced) in Flutter using Firebase(IOS & Android)

I love Flutter as much as anything because it makes our life easier in many ways. But it was not easy when I came across implementing Image…

blog.devgenius.io

제가 따라한 글입니다. 순서대로 따라하면서 생긴 오류가 3개 있었습니다.

 

첫번째로 생긴 오류는 아래와 같습니다.

Cycle inside Runner; building could produce unreliable results.

 

이는 Xcode -> Runner -> Target의 Runner -> Build Phases 에서 순서를 바꿔주면 됩니다.

Embed로 시작하는 Phase를 맨 위에 있는 Run Script 위에 위치해두시면 문제는 해결됩니다. 저 같은 경우 Firebase Crashlytics를 추가로 사용하기에 두번째 Run Script가 있지만 사용하지 않는 분들은 없기에 무시하셔도 됩니다.

 

이렇게 하고 나면 두번째 오류가 발생할 수 있습니다.

Command ValidateEmbeddedBinary failed with a nonzero exit code

The CFBundleVersion of an app extension ('1') must match that of its containing parent app ('31').

Xcode 상단 item bar

맨 오른쪽 아이콘을 누르시면 빌드에서 왜 실패했는지 알 수 있습니다. 저는 여기서 번들 버전이 맞지 않다는 오류를 발견했습니다. 

이는 Xcode -> Runner -> Target의 ImageNotification -> Build Setting -> [Ctrl + F] Versioning을 찾아 

Current Project Version(ex : 31)과 Marketing Version(ex : 1.3.61)을 기존 Target의 Runner 버전과 똑같이 맞춰줘야 합니다.

이렇게 하면 두번째 오류는 해결이 됩니다.

 

이렇게 하면 문제 없이 빌드는 되는데 알림에 이미지가 포함이 되지 않습니다.

 

세번째로 기존에 적어놓았던 NotificationService.swift를 아래 코드로 바꿔주시면 이미지가 포함이 됩니다. 위에 올려놓은 블로그의 코드와 달리 didReceive의 코드가 FirebaseMessage의 메소드로 되어 있습니다.

import UserNotifications
import FirebaseMessaging

class NotificationService: UNNotificationServiceExtension {
    
    private var contentHandler: ((UNNotificationContent) -> Void)?
    private var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        // 🔥 FirebaseMessaging
        guard let bestAttemptContent = bestAttemptContent else { return }
        FIRMessagingExtensionHelper().populateNotificationContent(bestAttemptContent, withContentHandler: contentHandler)
    }
    
    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)
        }
    }
}
extension UNNotificationRequest {
    var attachment: UNNotificationAttachment? {
        guard let attachmentURL = content.userInfo["image_url"] as? String, let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else {
            return nil
        }
        return try? UNNotificationAttachment(data: imageData, options: nil)
    }
}

extension UNNotificationAttachment {

    convenience init(data: Data, options: [NSObject: AnyObject]?) throws {
        let fileManager = FileManager.default
        let temporaryFolderName = ProcessInfo.processInfo.globallyUniqueString
        let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(temporaryFolderName, isDirectory: true)

        try fileManager.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil)
        let imageFileIdentifier = UUID().uuidString + ".jpg"
        let fileURL = temporaryFolderURL.appendingPathComponent(imageFileIdentifier)
        try data.write(to: fileURL)
        try self.init(identifier: imageFileIdentifier, url: fileURL, options: options)
    }
}

 

이렇게 되면 문제 없이 Push Notification의 이미지를 넣을 수 있습니다!

반응형
LIST

'Flutter' 카테고리의 다른 글

안녕하세요~ Smile Developer입니다.  (0) 2023.02.10