使用图像推送通知 - iOS - Swift

时间:2017-06-20 05:19:10

标签: ios swift image push-notification

您好我只想用图片显示推送通知。我使用下面的代码,我不知道我在哪里做错了它花了我超过3周,我经历了很多链接但仍然无法修复。以下是我的App代理代码

AppDelegate.Swift

import UIKit
import UserNotifications

var deviceTokenString:String = ""
var badgeCount = 0

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

var window: UIWindow?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // Push Notification

    if #available(iOS 10.0, *)
    {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in

            // actions based on whether notifications were authorised or not

            guard error == nil else {

                //Display Error.. Handle Error.. etc..

                return
            }

            if granted
            {

                //Do stuff here..

            }

            else {

                //Handle user denying permissions..

            }

        }

        application.registerForRemoteNotifications()
    } else {
        // Fallback on earlier versions
    }




    registerForRemoteNotification()


    // iOS 10 support
    if #available(iOS 10, *) {
        UNUserNotificationCenter.current().requestAuthorization(options:[.alert, .sound]){ (granted, error) in }
        application.registerForRemoteNotifications()
    }
        // iOS 9 support
    else if #available(iOS 9, *) {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
        // iOS 8 support
    else if #available(iOS 8, *) {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
        // iOS 7 support
    else {
        application.registerForRemoteNotifications(matching: [.sound, .alert])
    }

    return true
}

func registerForRemoteNotification() {
    if #available(iOS 10.0, *) {
        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.sound, .alert]) { (granted, error) in
            if error == nil{
                UIApplication.shared.registerForRemoteNotifications()

             //   UIApplication.shared.applicationIconBadgeNumber = 5
            }
        }
    }
    else {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()

      //  UIApplication.shared.applicationIconBadgeNumber = 5
    }
}

func incrementBadgeNumberBy(badgeNumberIncrement: Int)
{
    let currentBadgeNumber = UIApplication.shared.applicationIconBadgeNumber
    let updatedBadgeNumber = currentBadgeNumber + badgeNumberIncrement
    if (updatedBadgeNumber > 0)
    {
        UIApplication.shared.applicationIconBadgeNumber = updatedBadgeNumber
    }
    else
    {
        UIApplication.shared.applicationIconBadgeNumber = 0
    }
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("Couldn't register: \(error)")
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    deviceTokenString = deviceToken.hexString()

    //  deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print("device token: \(deviceTokenString)")


}

// Push notification received
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
    // Print notification payload data

    badgeCount = badgeCount + 1
    self.incrementBadgeNumberBy(badgeNumberIncrement: badgeCount)

    print("Push notification received: \(data)")

}

//  Notification will present call back
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .sound, .badge])


    print("UserInfo: \(notification.request.content.userInfo)")

    var userinfo = NSDictionary()
    userinfo = notification.request.content.userInfo as NSDictionary

    let imgData = userinfo.value(forKey: "data")! as! NSDictionary

    let url = imgData.value(forKey: "attachment-url")

    let imgUrl = URL(string: url as! String)!

    //  1. Create Notification Content
    let content = UNMutableNotificationContent()


    //  2. Create Notification Attachment

    URLSession.shared.downloadTask(with: imgUrl)
    {(location, response, error) in

        print("location: \(location!)")

        if error == nil
        {
            if let location = location
            {
                // Move temporary file to remove .tmp extension

                let tmpDirectory = NSTemporaryDirectory()

                let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent)

                print("tmpFile: \(tmpFile)")

                let tmpUrl = URL(string: tmpFile)!

                print("tmpUrl: \(tmpUrl)")

                try! FileManager.default.moveItem(at: location, to: tmpUrl)

                // Add the attachment to the notification content

                if let attachment = try? UNNotificationAttachment(identifier: "attachment", url: tmpUrl) {

                    content.attachments = [attachment]

                    print("attachment: \(content.attachments)")

                    //  3. Create Notification Request

                    let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue,

                                                             content: content, trigger: nil)

                    content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)"
                    content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)"
                    content.sound = UNNotificationSound.default()
                    content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber;
                    content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue

                    //  4. Add to NotificationCenter

                    let center = UNUserNotificationCenter.current()

                    center.add(request)
                }
            }
        }
        else
        {
            print("Error: \(error!)")
        }
        }.resume()
}

@available(iOS 10.0, *)
//  Notification interaction response call back
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {

    print("\(response.notification.request.content.userInfo)")

    var userinfo = NSDictionary()
    userinfo = response.notification.request.content.userInfo as NSDictionary

    let imgData = userinfo.value(forKey: "data")! as! NSDictionary

    let url = imgData.value(forKey: "attachment-url")

    let imgUrl = URL(string: url as! String)!

    //  1. Create Notification Content
    let content = UNMutableNotificationContent()
    content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)"
    content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)"
    content.sound = UNNotificationSound.default()
    content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber;
    content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue   //  设置通知类型标示

    //  2. Create Notification Attachment

    URLSession.shared.downloadTask(with: imgUrl) { (location, response, error) in

        if let location = location {

            // Move temporary file to remove .tmp extension

            let tmpDirectory = NSTemporaryDirectory()

            let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent)

            let tmpUrl = URL(string: tmpFile)!

            try! FileManager.default.moveItem(at: location, to: tmpUrl)



            // Add the attachment to the notification content

            if let attachment = try? UNNotificationAttachment(identifier: "", url: tmpUrl) {

                content.attachments = [attachment]
            }
        }

        // Serve the notification content

        // self.contentHandler!(content)

        }.resume()

    //        if let attachement = try? UNNotificationAttachment(identifier: "attachment", url: imgUrl, options: nil)
    //        {
    //            content.attachments = [attachement]
    //        }

    //  3. Create Notification Request
    let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue,
                                             content: content, trigger: nil)

    //  4. Add to NotificationCenter
    let center = UNUserNotificationCenter.current()
    center.add(request)

    let responseNotificationRequestIdentifier = response.notification.request.identifier

    if responseNotificationRequestIdentifier == String.UNNotificationRequest.NormalLocalPush.rawValue ||
        responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithTrigger.rawValue ||
        responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI1.rawValue ||
        responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI2.rawValue {

        let actionIdentifier = response.actionIdentifier
        switch actionIdentifier {
        case String.UNNotificationAction.Accept.rawValue:

            break
        case String.UNNotificationAction.Reject.rawValue:

            break
        case String.UNNotificationAction.Input.rawValue:

            break
        case UNNotificationDismissActionIdentifier:

            break
        case UNNotificationDefaultActionIdentifier:

            break
        default:
            break
        }
    }
    completionHandler();
}


}

extension Data
{
func hexString() -> String
{
    return self.reduce("") { string, byte in
        string + String(format: "%02X", byte)
    }
}
}

以下是我用于自定义推送通知的扩展码,

Extension.swift

import Foundation

extension String {

enum UNNotificationAction : String {
    case Accept
    case Reject
    case Input
}

enum UNNotificationCategory : String {
    case Normal
    case Cheer
    case CheerText
}

enum UNNotificationRequest : String {
    case NormalLocalPush
    case LocalPushWithTrigger
    case LocalPushWithCustomUI1
    case LocalPushWithCustomUI2
}
}

extension URL {

enum ResourceType : String {
    case Local
    case Local1
    case Remote
    case AttachmentRemote
}

static func resource(type :ResourceType) -> URL
{
    switch type {
    case .Local:
        return Bundle.main.url(forResource: "cheer", withExtension: "png")!
    case .Local1:
        return Bundle.main.url(forResource: "hahaha", withExtension: "gif")!
    case .Remote:
        return URL(string: "http://ww1.sinaimg.cn/large/65312d9agw1f59leskkcij20cs0csmym.jpg")!
    case .AttachmentRemote:
        return URL(string: "https://assets-cdn.github.com/images/modules/open_graph/github-mark.png")!
    }
    }
}

extension URLSession {

class func downloadImage(atURL url: URL, withCompletionHandler completionHandler: @escaping (Data?, NSError?) -> Void) {
    let dataTask = URLSession.shared.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in
        completionHandler(data, error as NSError?)
    }
    dataTask.resume()
}
}

和我的Api回复是,

[AnyHashable("aps"):
 {
alert =     {
    body = test;
    title = "N-Gal";
};
"mutable-content" = 1;
sound = default;
}, 
AnyHashable("data"): 
{
"attachment-url" = "https://www.n-gal.com/image/cache/catalog/HomeBanner/Banners/1172X450-N-Gal-Footwear-Banner-100x100.jpg";
}]

此代码基于教程https://github.com/maquannene/UserNotifications。请给我一个解决方案来解决这个问题...在此先感谢...!

1 个答案:

答案 0 :(得分:6)

从您的代码段我得出的结论是,您正在谈论远程通知。这是一个重要的区别。如果你想丰富'远程通知(例如添加图片),您需要UNNotificationServiceExtension

  

对于本地通知,应用在创建时添加附件   通知内容的其余部分。 将附件添加到遥控器   通知,使用通知服务扩展来修改   通知内容在发布之前。欲获得更多信息   关于实现通知服务扩展,请参阅   UNNotificationServiceExtension

来源:Apple documentation。 (强调我的)

该扩展程序位于您的应用程序之外,在用户看到远程通知之前被称为。这样,您可以在计划发送通知之前加载所有远程资源。有关扩展程序生命周期及其与主机应用程序通信方式的更多信息,请查看App Extension Programming Guide

要在Xcode中添加扩展程序,请转到File > New > Target并选择通知服务扩展程序

New target pane

这将创建新的扩展目标并将其嵌入主机目标:

New extension target

NotificationService.swift文件中,您将找到可以开始自定义通知内容的入口点。

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...
            bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"

            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)
        }
    }

}

请务必查看UNNotificationServiceExtension class overview了解详情。