如何正确接收PUSH通知?

时间:2018-02-14 06:40:30

标签: swift apple-push-notifications voip callkit pushkit

我正在使用Xcode 9.2,Swift 4.0编写VoIP应用程序,最低iOS版本是10.3。我想接收来电,即使iPhone处于睡眠模式(就像WhatsApp或Viber一样)。我已经知道我必须使用CallKit。但我不知道如何正确接收PUSH通知。我的意思是,我有两种方法可以接收它们。首先是在AppDelegate.swift中,请看(这种方法有效):

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

        //Getting permissions for Notifications
        //222
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
        }
        application.registerForRemoteNotifications()
        //222

        return true
    }

    //For PUSH Notifications settings

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("NOTIFICATION ERROR: \(error)")
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let pushToken = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}).lowercased()
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // Receiving call?
    }

}

但是,无论我正在做什么,如果iPhone正在睡觉,它也不会触发来电。最近我看到还有另一种接收PUSH通知的方法。请看:

import UIKit
import CallKit
import PushKit

class ViewController: UIViewController, CXProviderDelegate, PKPushRegistryDelegate {

    override func viewDidLoad() {
        let registry = PKPushRegistry(queue: nil)
        registry.delegate = self
        registry.desiredPushTypes = [PKPushType.voIP]
    }

    func providerDidReset(_ provider: CXProvider) {
    }

    func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        action.fulfill()
    }

    func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
        action.fulfill()
    }

    func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
        print(pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined())
    }

    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        // Receive call?
    }

}

问题是在第一种方法中我有这个PUSH标记:9bcf73ac3d6a68be07c26d8b6a972f5b716cd5308f1a19048b62d19b9b8d4bd1

第二种方法返回此PUSH令牌: 1e40fafb2963161b1bcf1bdde00d625a879c6934e19e2fb32f62b1c9272e956f

他们不平等!怎么会这样?因此,主要问题是:如何接收PUSH通知以及AppDelegate和PushKit方法之间有什么区别以及哪个令牌是正确的?

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

首先删除此行application.registerForRemoteNotifications()

现在来到puskit下面的方法会有正确的令牌

   func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, forType type: PKPushType) {
    print("\(#function) voip token: \(credentials.token)")

    let deviceToken = credentials.token.reduce("", {$0 + String(format: "%02X", $1) })
    print("\(#function) token is: \(deviceToken)")}

并且Push-kit框架没有像远程或本地通知这样的UI,您需要在每次调用以下方法时触发本地通知

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    // Receive call?
}