Search code examples
flutterpush-notificationfirebase-cloud-messagingapple-push-notificationsflutter-local-notification

Flutter Image Notification


Flutter Image notification not working background & terminated.It's work correctly in foreground. Download a image and save temp directory(Directory.systemTemp) and get a path to show the image in foreground

`if (Platform.isIOS) {
    if (message.data['image'] != null) {
      url = message.data['image'];
      var formatname = url.toString().split(".");
      var length = formatname.length - 1;
      var format = formatname[length];
      log("message$format");
      var formatlist = ['jpg', 'gif', 'png'];
      bigpicture = await DownloadUtil.downloadfiles(url,
          "bigpicture.${(format.isEmpty || formatlist.contains(format)) ? format : "jpg"}");
      print(bigpicture);
    } else {
      bigpicture = " ";
    }
  } 
}`

flutter Local Notifications Plugin vesion (flutter_local_notifications: ^9.2.0). firebase messaging package vesion (firebase messaging:^11.2.5).

`flutterLocalNotificationsPlugin.show(
        id,
        message.data["title"],
        message.data["body"],
        NotificationDetails(
          iOS: ios != null
              ? IOSNotificationDetails(
                  attachments: message.data['image'] != null
                      ? <IOSNotificationAttachment>[
                          IOSNotificationAttachment(bigpicture),
                        ]
                      : <IOSNotificationAttachment>[],
                )
              : null,
        ),
        payload: json.encode(message.data));`

payload:-

`{
    "message": {
        "notification": {
            "title": "Welcome message",
            "body": "Firebase Nodification Success",
            "sound": "Default",
            "imageUrl": "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
        },
        "data": {
            "title": "Welcome message12",
            "body": "Firebase Nodification Success🙂",
            "click_action": "FLUTTER_NOTIFICATION_CLICK",
            "image": "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg",
            "status": "Received"
        }
    },
    "registrationToken": "**fcmtoken**"
}`

flutter Doctor:-

`Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.10.5, on macOS 12.5.1 21G83 darwin-arm, locale en-IN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.69.2)
[✓] Connected device (2 available

[✓] HTTP Host Availability
• No issues found!`

Solution

  • payload:-

    {
     "notification": {
         "title": "New image",
         "body": "Check out this cool image!"
     },
     "data": {
         "title": "Example Notification001",
         "body": "Check out this cool image!:slightly_smiling_face:",
         "click_action": "FLUTTER_NOTIFICATION_CLICK",
         "image": "https://img.freepik.com/free-photo/chicken-wings-barbecue-sweetly-sour-sauce-picnic-summer-menu-tasty-food-top-view-flat-lay_2829-6471.jpg"
     },
     "apns": {
         "payload": {
             "aps": {
                 "mutable-content": 1,
                 "sound": "Default"
             }
         }
     },
     "registrationToken": [
         "**Your fcm token**"
     ]
    } 
    

    Create Notification Service Extension

    After you have successfully created the iOS application you need to create a notification service extension. Here are the steps of how to create a notification service extension.

    1. In the Xcode menu, go to File > New > Target.

    2. Select the Notification Service Extension.

    3. Gives the name of the Extension service and click the finish button.

    enter image description here

    [![enter image description here][2]][2]

    Type a product name is your wish(example:-ImageNotificationService)

    your add firebase Messaging package in xcode (this line are install firebase messaging in your package )(target 'this your notification service contact name')

    target 'ImageNotificationService' do
      use_frameworks!
      pod 'Firebase/Messaging'
    end
    

    This Info.plist in imagenotificationservice folder plist

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>NSExtension</key>
        <dict>
            <key>UNNotificationExtensionCategory</key>
            <string>imageNotificationCategory</string>
            <key>NSExtensionAttributes</key>
            <dict>
                <key>UNNotificationExtensionDefaultContentHidden</key>
                <false/>
                <key>UNNotificationExtensionInitialContentSizeRatio</key>
                <real>1</real>
            </dict>
            <key>NSExtensionPointIdentifier</key>
            <string>com.apple.usernotifications.service</string>
            <key>NSExtensionPrincipalClass</key>
            <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
        </dict>
    </dict>
    </plist>
    

    This line is notificationservice.swift

    import UIKit
    import UserNotifications
    import FirebaseMessaging
    
    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)
            guard let bestAttemptContent = bestAttemptContent else { return }
            // Modify the notification content here as you wish
            let data = bestAttemptContent.userInfo as NSDictionary
            let pref = UserDefaults.init(suiteName: "group.id.gits.notifserviceextension")
            pref?.set(data, forKey: "NOTIF_DATA")
            pref?.synchronize()
            NSLog("notificationserviceExtension")
            guard let attachmentURL = data["image"] as? String else {
                        contentHandler(bestAttemptContent)
                        return
                    }
            do {
                 print("unNotification sucesss01---\(attachmentURL)")
                let imageData = try Data(contentsOf: URL(string: attachmentURL)!)
                guard let attachment = UNNotificationAttachment.create(imageFileIdentifier: "image.jpg", data: imageData, options: nil) else {
                    contentHandler(bestAttemptContent)
                    return
                }
                bestAttemptContent.attachments = [attachment]
                contentHandler(bestAttemptContent.copy() as! UNNotificationContent)
                
            } catch {
                self.bestAttemptContent?.title = "\(self.bestAttemptContent?.title ?? "")."
                self.bestAttemptContent?.body = "\(self.bestAttemptContent?.body ?? "")"
                contentHandler(bestAttemptContent)
                print("Unable to load data: \(error)")
    
            }
        }
        
        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 UNNotificationAttachment {
        static func create(imageFileIdentifier: String, data: Data, options: [NSObject: AnyObject]?) -> UNNotificationAttachment? {
            let fileManager = FileManager.default
            let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
            let tmpSubFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
    
            do {
                try fileManager.createDirectory(at: tmpSubFolderURL, withIntermediateDirectories: true, attributes: nil)
                let fileURL = tmpSubFolderURL.appendingPathComponent(imageFileIdentifier)
                try data.write(to: fileURL)
                let attachment = try UNNotificationAttachment(identifier: imageFileIdentifier, url: fileURL, options: options)
                return attachment
            } catch {
                print("Error creating attachment: \(error)")
            }
            return nil
        }
    }
    
    
    

    Incase if you haven any queries comment them below:-