使用PushKit无法接收VoIP通知。

4
我正在按照这篇文章M Penades'的答案构建VoIP通知演示。我能够使用didRegisterUserNotificationSettings注册通知,并可以从didUpdatePushCredentials获取VoIP令牌。

但是,当我使用houston模拟向我的设备发送通知时,我可以从控制台得到1 push notification sent successfully的消息,但在设备端没有任何操作或日志。看起来didReceiveIncomingPushWithPayload从未被调用。

P.S. 我正在使用Xcode 7.3,iPhone 6(iOS 9.3)和iPad Mini(iOS 9.3)进行开发。分发Ad Hoc ipa以供安装。

这里发布了代码。

import UIKit
import PushKit


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
let voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    //Enable all notification type. VoIP Notifications don't present a UI but we will use this to show local nofications later
    let notificationSettings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound] , categories: nil)

    //register the notification settings
    application.registerUserNotificationSettings(notificationSettings)

    //output what state the app is in. This will be used to see when the app is started in the background
    NSLog("app launched with state \(application.applicationState.stringValue)")
    return true
}

    func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    //output to see when we terminate the app
    NSLog("app terminated")
}

}

extension AppDelegate {

func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {

    //register for voip notifications
    NSLog("didRegisterUserNotificationSettings called")
    voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
    voipRegistry.delegate = self;
}
}

extension AppDelegate: PKPushRegistryDelegate {


func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
    NSLog("didUpdatePushCredentials called")

    //print out the VoIP token. We will use this to test the nofications.
    NSLog("voip token: \(credentials.token)")
}

func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {

    NSLog("didReceiveIncomingPushWithPayload called")


    let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
    let message = payloadDict?["alert"]

    //present a local notifcation to visually see when we are recieving a VoIP Notification
    if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
        NSLog("incoming notificaiton from background")

        let localNotification = UILocalNotification();
        localNotification.alertBody = message
        localNotification.applicationIconBadgeNumber = 1;
        localNotification.soundName = UILocalNotificationDefaultSoundName;

        UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
    }

    else {
        NSLog("incoming notificaiton from frontend")


        dispatch_async(dispatch_get_main_queue(), { () -> Void in


            let alertController = UIAlertController(title: "Title", message: "This is UIAlertController default", preferredStyle: UIAlertControllerStyle.Alert)
            let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
            let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
            alertController.addAction(cancelAction)
            alertController.addAction(okAction)

            UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

        })
    }

    NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}

func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
    NSLog("didInvalidatePushTokenForType called")
    NSLog("token invalidated")
}
} 

extension UIApplicationState {

//help to output a string instead of an enum number
var stringValue : String {
    get {
        switch(self) {
        case .Active:
            return "Active"
        case .Inactive:
            return "Inactive"
        case .Background:
            return "Background"
        }
    }
}
}

有没有关于如何接收这样的通知的想法?

1
我之前也遇到了相同的问题。当我尝试使用 node-apn 发送通知时,我收到了一个错误信息。看起来 Houston 控制台工具在某些情况下不会显示错误。此外,请确保您使用了正确的标识符和证书。 - ujell
你最终在设备上收到了通知吗?我贴出的原生Swift代码需要做任何更改吗?谢谢。 - Shongsu
在我的情况下,我试图使用错误的.pem文件发送通知,所以是的,这已经被解决了。还请注意开发和分发的设备令牌是不同的,这也可能是你的问题。如果我没有漏掉任何东西,代码看起来是没有问题的。 - ujell
1
谢谢!你救了我的命。我把服务器地址从gateway.sandbox.push.apple.com(用于开发)改成了gateway.push.apple.com(用于生产环境,我认为对于VoIP推送,这是唯一的选项)。最终我收到了推送消息。 - Shongsu
请查看:https://stackoverflow.com/questions/48581495/ios-silent-push-should-update-application-badge-count/48581601#48581601 - Chandresh Kachariya
1个回答

8
最后我解决了这个问题。对于Swift源代码没有问题,问题在于我错误地将推送请求发送到苹果的开发服务器gateway.sandbox.push.apple.com,实际上我们应该将请求发送到苹果的生产服务器gateway.push.apple.com
如果您正在遵循M Penades的程序,请注意您需要修改Simplepush脚本,只需在第20行将ssl://gateway.sandbox.push.apple.com:2195替换为ssl://gateway.push.apple.com:2195并重试。
希望对你有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接