0
1

More than 3 years have passed since last update.

MarketingCloudSDK iOSでリッチPush通知を送信する

Last updated at Posted at 2020-08-16

環境

・xcode Version 11.3.1 (11C504)
・swift Version 5.1.3
・MarketingCloudSDK iOS (v7.2.1)
・Mac OS 10.14.6(Mojave)

準備

MarketingCloudSDK iOSでシンプルなpush通知を送信する
の続きとなります。

リッチPushとは

push通知を開くと遷移したいurlに飛べたり、push通知に画像、動画などを表示することができる。

リッチPush通知の実装

1.opendirect機能(ディープリンクとも呼ばれる)

AppDelegate.swift
MarketingCloudSDK.sharedInstance().sfmc_setURLHandlingDelegate(self)

上記コードをSDKの初期設定記述の後に、AppDelegate.swift内に記述する。
その後、
MarketingCloudSDKURLHandlingDelegateプロトコルメソッドを追加

AppDelegate.swift
extension AppDelegate: MarketingCloudSDKURLHandlingDelegate {
    func sfmc_handle(_ url: URL, type: String) {
        print(url)
        if UIApplication.shared.canOpenURL(url) == true {
            // ios 10.0以上
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: { success in
                    if success {
                        print("url \(url) opened successfully")
                    } else {
                        print("url \(url) could not be opened")
                    }
                })
            } else {
                if UIApplication.shared.openURL(url) == true {
                    print("url \(url) opened successfully")
                } else {
                    print("url \(url) could not be opened")
                }
            }
        }
    }
}

※指定できるのは「:」を含むURL形式の値のみ

2.push通知に画像、動画などを表示する

xcode上でNotification Service Extensionを作成する

File → New → target...を選択する
スクリーンショット 2020-08-05 11.43.10.png
Notification Service Extensionを選択してNextをクリックする
スクリーンショット_2020_08_05_11_45.png
productnameを入力してfinishボタンをクリックする
スクリーンショット 2020-08-05 11.49.39.png
上記のようなポップアップがでてきたらActivateをクリックする

Notification Service Extensionの実装
Notification Service Extensionのフォルダができるので、その中のNotificationService.swiftに実装をしていく

実装イメージは下記となります

AppDelegate.swift
/*
 * Copyright (c) 2017, salesforce.com, inc.
 * All rights reserved.
 * Licensed under the BSD 3-Clause license.
 * For full license text, see LICENSE.txt file in the repo root  or https://opensource.org/licenses/BSD-3-Clause
 */

import CoreGraphics
import UserNotifications

class NotificationService: UNNotificationServiceExtension {
    var contentHandler: ((_ contentToDeliver: UNNotificationContent) -> Void)? = nil
    var modifiedNotificationContent: UNMutableNotificationContent?

    func createMediaAttachment(_ localMediaUrl: URL) -> UNNotificationAttachment {
        // options: specify what cropping rectangle of the media to use for a thumbnail
        //          whether the thumbnail is hidden or not
        let clippingRect = CGRect.zero
        let mediaAttachment = try? UNNotificationAttachment(identifier: "attachmentIdentifier", url: localMediaUrl, options: [UNNotificationAttachmentOptionsThumbnailClippingRectKey: clippingRect.dictionaryRepresentation, UNNotificationAttachmentOptionsThumbnailHiddenKey: false])
        return mediaAttachment!
    }

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

        // save the completion handler we will call back later
        self.contentHandler = contentHandler

        // make a copy of the notification so we can change it
        modifiedNotificationContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        // does the payload contains a remote URL to download or a local URL?
        if let mediaUrlString = request.content.userInfo["_mediaUrl"] as? String {
            // see if the media URL is for a local file  (i.e., file://movie.mp4)
            guard let mediaUrl = URL(string: mediaUrlString) else {
                // attempt to create a URL to a file in local storage
                var useAlternateText: Bool = true
                if mediaUrlString.isEmpty == false {
                    let mediaUrlFilename:NSString = mediaUrlString as NSString
                    let fileName = (mediaUrlFilename.lastPathComponent as NSString).deletingPathExtension
                    let fileExtension = (mediaUrlFilename.lastPathComponent as NSString).pathExtension

                    // is it in the bundle?
                    if let localMediaUrlPath = Bundle.main.path(forResource: fileName, ofType: fileExtension) {
                        // is the URL a local file URL?
                        let localMediaUrl = URL.init(fileURLWithPath: localMediaUrlPath)
                        if localMediaUrl.isFileURL == true {
                            // create an attachment with the local media
                            let mediaAttachment: UNNotificationAttachment? = createMediaAttachment(localMediaUrl)

                            // if no problems creating the attachment, we can use it
                            if mediaAttachment != nil {
                                // set the media to display in the notification
                                modifiedNotificationContent?.attachments = [mediaAttachment!]

                                // everything is ok
                                useAlternateText = false
                            }
                        }
                    }
                }

                // if any problems creating the attachment, use the alternate text if provided
                if (useAlternateText == true) {
                    if let mediaAltText = request.content.userInfo["_mediaAlt"] as? String {
                        if mediaAltText.isEmpty == false {
                            modifiedNotificationContent?.body = mediaAltText
                        }
                    }
                }

                // tell the OS we are done and here is the new content
                contentHandler(modifiedNotificationContent!)
                return
            }

            // if we have a URL, try to download media (i.e., https://media.giphy.com/media/3oz8xJBbCpzG9byZmU/giphy.gif)
            if mediaUrl.isFileURL == false {
                // create a session to handle downloading of the URL
                let session = URLSession(configuration: URLSessionConfiguration.default)

                // start a download task to handle the download of the media
                weak var weakSelf: NotificationService? = self
                session.downloadTask(with: mediaUrl, completionHandler: {(_ location: URL?, _ response: URLResponse?, _ error: Error?) -> Void in
                    var useAlternateText: Bool = true
                    // if the download succeeded, save it locally and then make an attachment
                    if error == nil {
                        let downloadResponse = response as! HTTPURLResponse
                        if (downloadResponse.statusCode >= 200 && downloadResponse.statusCode <= 299) {
                            // download was successful, attempt save the media file
                            let localMediaUrl = URL.init(fileURLWithPath: location!.path + mediaUrl.lastPathComponent)

                            // remove any existing file with the same name
                            try? FileManager.default.removeItem(at: localMediaUrl)

                            // move the downloaded file from the temporary location to a new file
                            if ((try? FileManager.default.moveItem(at: location!, to: localMediaUrl)) != nil) {
                                // create an attachment with the new file
                                let mediaAttachment: UNNotificationAttachment? = weakSelf?.createMediaAttachment(localMediaUrl)

                                // if no problems creating the attachment, we can use it
                                if mediaAttachment != nil {
                                    // set the media to display in the notification
                                    weakSelf?.modifiedNotificationContent?.attachments = [mediaAttachment!]

                                    // everything is ok
                                    useAlternateText = false
                                }
                            }
                        }
                    }

                    // なにか問題が起こり、代替テキストを設定している場合は代替テキストを表示
                    if (useAlternateText == true) {
                        if let mediaAltText = request.content.userInfo["_mediaAlt"] as? String {
                            if mediaAltText.isEmpty == false {
                                weakSelf?.modifiedNotificationContent?.body = mediaAltText
                            }
                        }
                    }

                    // tell the OS we are done and here is the new content
                    weakSelf?.contentHandler!((weakSelf?.modifiedNotificationContent)!)
                }).resume()
            }
        }
        else {
            // no media URL found in the payload, just pass on the orginal payload
            contentHandler(request.content)
            return
        }
    }

    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.
        // we took too long to download the media URL, use the alternate text if provided
        if let mediaAltText = modifiedNotificationContent?.userInfo["_mediaAlt"] as? String {
            // alternative text to display if there are any issues loading the media URL
            if mediaAltText.isEmpty == false {
                modifiedNotificationContent?.body = mediaAltText
            }
        }

        // 取得に失敗したときの処理
        contentHandler!(modifiedNotificationContent!)
    }
}

※動画はmp4に対応

SMCからリッチPush通知を送信する

無事とどけばOK

参考リンク(公式)

https://salesforce-marketingcloud.github.io/MarketingCloudSDK-iOS/sdk-implementation/implementation-urlhandling.html
https://salesforce-marketingcloud.github.io/MarketingCloudSDK-iOS/push-notifications/rich-notifications.html

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1