Programming/Swift

[Swift] iOS Push Image도 받아보기(Feat.FCM) 2/2

ilovecoffee 2020. 9. 1. 10:13

안녕하세요.

1/2는 어디갔냐구요? 1/2는 귀찮아서 2/2 먼저 보고 할려구용ㅋㅋㅋ

오늘은 다음과 같이 ImagePush로 받는 방법을 공부해보려고 합니다.

새로 만드는 앱때문에 테스트 해보면서 진행했습니당

전제조건은 기본적인 FCM 구성과 기본적인 푸시는 날려보시고 오셔야한다는 점입니다?

(곧 작성해보지요..)

원래는 글 쓸 생각을 안해서..ㅠㅠ

제 의식대로 글을 써보겠습니다! 그럼 출발!

 

 

자 기본적으로 FCM을 받으면 앱이 포어그라운드에 있을 때에는

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
	let userInfo = notification.request.content.userInfo
	completionHandler([.alert, .badge, .sound])
 }

위와 같은 함수에서 동작을 하구요.

 

앱이 백그라운드에 있을 때나, 아예 종료되었을 때는

 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
 	let userInfo = response.notification.request.content.userInfo
    completionHandler()
  }

위와 같은 함수에서 동작을 합니다.

 

그런데, FCM에서 테스트 해보신 분은 알겠지만 저 userInfo를 print해보시면 알겠지만, 이미지를 넣어서 보내시면 분명히 넘어오는 데, 

푸시에는 표시가 안된단 말이에용? 짱나네

 

이미지 푸시를 날릴 일이 크게 많지 않았던 저는 어제 7시간을 어슬렁 어슬렁 찾아헤매었습니다.

그리고 다음 날인 오늘 출근해서 30분만에 테스트를 성공적으로 완료했습죠;;

 

먼저 프로젝트 파일창으로 가주신 후, 프로젝트 제일 상단으로 가주세요.

 

 

 

숫자 1번에 있는 +를 눌러주시구요.

 

 

Notification Service Extension 을 눌러서 생성해주세요.

 

이름을 주셔야 하는 데 전 그냥 Notification Service Extension이라고 주었어요.

 

그러고 나시면 Target이 생성되었을꺼에요.

 

좌측을 한 번 볼까요?

target이 생성되었으니, 그에 맞는 파일들이 생성됩니다.

NotifiactionService.swift 파일을 열어보시면

 

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...
            
             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)  
            print("serviceExtensionTimeWillExpire")
        }
    }
    
}

이렇게 생성되어있을껍니다.

 

didReceive(_:request:withContentHandler)

이 메서드가 받아온 데이터를 입맛에 맞게끔 수정하실 수 있는 부분입니다.

 

FCM data에서 이미지를 받아와야하는 데, 이미지를 받아올 수가 없어요? (이런 젠장)

 

구글링을 해보면 FirebaseMessaging을 임포트를 해줘서 수정해줘야 이미지가 들어가있는 푸시를 보여줄  수 있대요..(제 의식대로의 해석..)

 

함 해볼까여 따라오세요.

 

그래서 굳이 새로 만든 Notification Service Extensions에 Firebase/Messaging을 설치해주셔야한답니다.

 

target 'NotificationServiceExtension(처음 만드실 때 이름주어주신 걸로 해주세욥)' do
use_frameworks!
pod 'Firebase/Messaging'
end

 저는 cocoapods를 사용중이기 땜시롱 이렇게 추가해주었습니다.

 

설치만 해서는 안되고.. 따로 작업을 해주셔야합니다.

 

작업을 어떻게 하냐면요? 

 

이렇게 합니다. 처음 열었을 때와 비교해볼까요?

 

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...
            
             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)  
            print("serviceExtensionTimeWillExpire")
        }
    }
    
}

요거시 전이구요.

 

 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...
            
            let apsData = request.content.userInfo["aps"] as! [String : Any]
            let alertData = apsData["alert"] as! [String : Any]
            let imageData = request.content.userInfo["fcm_options"] as! [String : Any]
            bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
            bestAttemptContent.body = "\(bestAttemptContent.body) [modified]"
            
            guard let urlImageString = imageData["image"] as? String else {
                contentHandler(bestAttemptContent)
                return
            }
            if let newsImageUrl = URL(string: urlImageString) {
                
                guard let imageData = try? Data(contentsOf: newsImageUrl) else {
                    contentHandler(bestAttemptContent)
                    return
                }
                guard let attachment = UNNotificationAttachment.saveImageToDisk(fileIdentifier: "newsImage.jpg", data: imageData, options: nil) else {
                    contentHandler(bestAttemptContent)
                    return
                }
                
                
                bestAttemptContent.attachments = [ attachment ]
            }
            Messaging.serviceExtension().populateNotificationContent(bestAttemptContent, withContentHandler: self.contentHandler!)
            
            contentHandler(bestAttemptContent)
        }
    }

아래가 후입니다.

 

기본적으로 bestAttemptContent를 사용해서 Title이나 body를 수정해서 사용하는데요.

 

Push를 보낼 때, 

 

알림 이미지를 다음과 같이 보내면 

 


            let imageData = request.content.userInfo["fcm_options"] as! [String : Any]
            
            guard let urlImageString = imageData["image"] as? String else {
                contentHandler(bestAttemptContent)
                return
            }
            if let newsImageUrl = URL(string: urlImageString) {
                
                guard let imageData = try? Data(contentsOf: newsImageUrl) else {
                    contentHandler(bestAttemptContent)
                    return
                }
                guard let attachment = UNNotificationAttachment.saveImageToDisk(fileIdentifier: "newsImage.jpg", data: imageData, options: nil) else {
                    contentHandler(bestAttemptContent)
                    return
                }
                
                
                bestAttemptContent.attachments = [ attachment ]
            }

 

 

위 코드를 통해서 수정할 수 가 있습니다.

 

이미지를 가져오는거에용.

 

위에 전과 후를 비교했을 때처럼  '' 코드를 참고하시고 테스트 함 해보시죠.

 

 

 

데이터를 위와 같이 넣고 푸시해볼게요!

 

 

다음과 같이 쨘!! 하고 나온답니다.

얼른 돌아와서 기아 좀 살려죠...

자 성공했습니다. 쉽져?

 

하루죙일 걸렸어요 ㅎ..

 

길게 적긴 했는 데, 영양가가 1도 없네요 ㅎㅎ..

 

데이터가 들어오면, 이제 WillPresent에서 데이터에 따라 다음 뷰컨으로 연결할지 결정하시면 됩니다.

 

 

다음에 봐요 안녕

 

Push Data를 받게되면..

아래와 같은 형식으로 데이터가 올텐데요.

이미지도 저 안에 fcm_options에 있는 image를 가져다 뿌려준건데.. 아무튼

 

[
"google.c.a.udt": 0,
 "google.c.sender.id": ,
  "google.c.a.ts": ,
   "title": (테스트)스파오 클리어런스 200종,
    "gcm.message_id": ,
     "imageurl": https://i.ytimg.com/vi/7qkbRYM7YP8/maxresdefault.jpg,
     "category":image-test,
      "google.c.a.c_id": ,
       "body":[광고] 육사시미 등 [유료배송], 
       "google.c.a.c_l": Push_20200713,
        "google.c.a.e": 1, 
        "subTitle": (테스트) 200종,
         "gcm.n.e": 1,
          "subBody": [광고] 육사시미 등 [유료배송], 
          "fcm_options": {
    			image = "https://blogfiles.pstatic.net/MjAyMDA4MjhfMjEw/MDAxNTk4NTgxOTgwOTQ3.D8Yn7SgOhPR7xCRXe5bA9QDhwDRKCuL2qSzhbh1O7Ckg.w5_VOPzfjSN0WuUkBiVQFsZ-Ba0Pwj0cXEqamVOz0a0g.JPEG.shoppingfolder/20200828_spao.jpg?type=w1";
		},
		 "aps": {
	    alert =     {
    	    body = "[\Uad11\Uace0] \Uc5ed\Ub300\Uae09\Ud560\Uc778 \Ud2f0\Uc154\Uce20/\Ub9e8\Ud22c\Ub9e8/\Uc790\Ucf13 \Ub4f1 [\Uc720\Ub8cc\Ubc30\Uc1a1]";
        	title = "[\Uad11\Uace0] \Uc721 \Uc0ac\Uc2dc\Ubbf8 \Uba39\Uace0\Uc2f6\Ub2e4.";
    	};
    	"mutable-content" = 1;
}
]

 

하단에 보시면 mutable-content = 1이 되어있어야. 이미지나 미디어를 표현해줄 수 있습니다.

꼭 체크해보시고 진행하세요!

'Programming > Swift' 카테고리의 다른 글

[iOS] Your enrollment could not be completed  (4) 2020.09.18
[Swift] Touch-id, Face-id를 적용해봐요.  (0) 2020.09.04
NSString 앞글자 비교.  (0) 2016.05.20
swift2.2 AppDelegate에 대하여..  (0) 2016.05.19
함수 타입과 호출  (0) 2015.11.30