当前位置: 首页 > 知识库问答 >
问题:

原因:“杀死应用程序,因为它在收到PushKit VoIP推送回调后从未向系统发布过传入呼叫。

燕航
2023-03-14

我正在寻找解决办法,但还没有找到。我的应用程序只接收VoIP推送,在iOS 13之后,当应用程序处于后台模式时,我无法再接收推送。我查看了其他问题,但我无法用建议的解决方案解决我的问题。有人能帮我吗?

在iOS13.0及更高版本上,必须在接收到传入的IP语音呼叫时以及在didReceiceIncomingPush()方法使用CallKit框架完成执行之前报告,否则系统将终止您的应用程序。

多次未能报告呼叫可能会阻止您的应用程序接收更多来电通知。

基本上,您不能再将VoIP推送用于非VoIP消息传递,并且需要对这些消息使用常规推送通知。

我阅读了此公告,但在我的应用程序中,对于特定类型的推送VoIP,我无法使用functionreportNewIncomingCall(),因为它需要参数,例如:uuid、hander、hasVideo ecc。这些参数不存在于有效负载中。

共有3个答案

华萧迟
2023-03-14

这不是有效载荷的问题。您可以创建自己的有效负载。你只需要在这个回调中调用下面的函数。

func pushRegistry(_ registry: PKPushRegistry, did接收传入推送有效载荷: PKPushPayload, for type: PKPush类型, 完成: @escaping () -

否则,苹果会暂时屏蔽推送通知。

provider.reportNewIncomingCall(with: uuid, update: update) { error in
completion() }

温举
2023-03-14

如果要将传入调用实现为另一个函数,并按如下方式调用它。它不起作用

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

相反,请尝试以下操作:

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

            print("didReceiveIncomingPushWith payload")

            if let callerID = payload.dictionaryPayload["callerID"] as? String,
                let hasVideo = payload.dictionaryPayload["hasVideo"] as? Bool{
                let update = CXCallUpdate()
                 update.remoteHandle = CXHandle(type: .generic, value: callerID)
                 update.hasVideo = hasVideo


                 let bgTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
                self.provider?.reportNewIncomingCall(with: UUID(), update: update, completion: { (_) in
                    completion()
                })
                UIApplication.shared.endBackgroundTask(bgTaskID)
            }
        completion()
    }

这实现了调用提供者在< code > push registry:didReceiveIncomingPushWith payload with completion handler 函数内发布调用请求。这对我很有效。

使用终端命令尝试VOIP请求:

curl -v -d '{"callerID": "test@test.com", "uuid":"YourUDIDorEmptyField", "hasVideo": false}' --http2 --cert yourvoipcertificatepemfile_Here.pem:pemfilePassword_Here https://api.development.push.apple.com/3/device/yourDeviceTokenID_generated_with_update_push_credentials_with_token_Here

替换:

>

  • test@test.com CXHandle.Handle上的相关详细信息键入如果是您的来电者姓名(.通用)或电子邮件(.email地址)或电话号码(.电话号码

    YourUDIDorEmptyField与您的UUID关联,或者您可以将其保留为空,因为

    <code>“hasVideo”:false</code>这里false是一个<code>布尔值(true/false)</code>,它处理来电屏幕上的<code>音频/视频</code>呼叫状态,您可以使用它通过实现它来准确地识别呼叫类型。

    yourvoipcertificatepemfile_Here是从 voip 证书(voipcertificate.cer导出的 .pem 文件的名称,不是直接从开发人员帐户导出的,而是在从开发人员帐户生成并安装到您的计算机之后导出的。然后在你的钥匙串里 -

    < code > PEM file password _ Here 是您在导出< code >时提供的密码。pem文件。(参考第4点。)

    您的DeviceTokenID_generated_with_update_push_credentials_with_token_Here应替换为通过以下PKPushRegistryDelegate Delegate方法生成的 令牌

    func push注册表(_注册表:PKPush注册表,didUpdate pushCreentals:PKPushCreentals,用于类型:PKPushType){

    let parts = pushCredentials.token.map { String(format: "%02.2hhx", $0) }
    
    let token = parts.joined()
    print("did update push credentials with token: \(token)") }
    

    如果您有任何疑问,请告诉我。我已经在应用程序的前台、后台、锁定屏幕上进行了尝试和测试,甚至在应用程序从最近的应用程序中删除后。(iOS13.4.1和Xcode版本11.4(11E146))

  • 宋飞文
    2023-03-14

    从iOS13开始,您只能使用VoIP推送来报告来电。对于不是来电的推送,您必须使用其他替代方案(请看这里的答案)。

    多次未能报告呼叫可能会阻止您的应用程序接收更多来电通知。

    从我的测试中,它似乎在仅报告2或3次失败后阻止了所有VoIP推送,并且它将在24小时左右保持阻止状态。

    因为它需要参数,比如:uuid、handle、hasVideo ecc。这些参数在有效载荷中不存在

    如果您收到新来电的VoIP推送,但仍然没有上面列出的所需信息,您可以使用“虚拟”值初始化呼叫,然后更新它们。例如,将remoteHandle设置为CXHandle(类型:.generic,值:“Connecting…”),然后用正确的值更新它:

    cxCallUpdate.remoteHandle = CXHandle(type: .emailAddress, value: "email@mail.com")
    cxProvider.reportCall(with: callUid, updated: cxCallUpdate)
    
     类似资料: