Ios 原因:';关闭应用程序,因为它在收到PushKit VoIP推送回调后从未向系统发送传入呼叫;

Ios 原因:';关闭应用程序,因为它在收到PushKit VoIP推送回调后从未向系统发送传入呼叫;,ios,swift,voip,callkit,pushkit,Ios,Swift,Voip,Callkit,Pushkit,我正在寻找解决办法,但还没有找到任何办法。我的应用程序只接收VoIP推送,在iOS 13之后,当应用程序处于后台模式时,我无法再接收推送。我看了看其他问题,但我无法用提出的解决方案解决我的问题。 有人能帮我吗 在iOS 13.0及更高版本上,必须在收到IP语音呼叫时以及在didReceiceIncomingPush()方法完成执行之前,使用CallKit框架报告传入的IP语音呼叫,否则系统将终止您的应用程序 重复报告呼叫失败可能会阻止您的应用程序接收更多来电通知 基本上,您不能再将VoIP推送用

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

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

重复报告呼叫失败可能会阻止您的应用程序接收更多来电通知

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

我读过这个公告,但在我的应用程序中,对于特定类型的推送VoIP,我不能使用函数
reportNewIncomingCall()
,因为它需要一些参数,如:uuid、handle、hasVideo ecc。
而且这些参数不存在于有效负载中。

由于iOS 13,您只能使用VoIP推送来报告传入呼叫。对于不是传入呼叫的推送,您必须使用其他替代方法(在此处查看)

重复报告呼叫失败可能会阻止您的应用程序接收更多来电通知

从我的测试来看,它似乎在只报告了2到3次失败后就阻止了所有的VoIP推送,并且它会被阻止大约24小时

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

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

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

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

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

否则,苹果将暂时阻止推送通知

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

如果您将传入调用实现为另一个函数,并按如下方式调用它。这行不通

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()
    }
这已经在
pushRegistry: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.HandleType上的相关详细信息
    如果是您的呼叫者姓名(
    .generic
    )或电子邮件(
    .emailAddress
    )或电话号码(
    .phoneNumber

  • YourUDIDorEmptyField
    和您的
    UUID
    或者当
    reportNewIncomingCall(使用:UUID(),update:callUpdate)
    在代码本身中初始化
    UUID()
    时,您可以将其保持为空

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

  • yourvoipcertificatepemfile\此处
    是您从voip证书导出的
    .pem
    文件的名称(
    voipcertificate.cer
    不是直接生成的,而是从开发人员帐户生成并安装到您的机器上之后。然后在
    keychain->mycertificates
    中将其导出为
    .pem
    带有密码的文件(
    pemfilePassword\u此处

  • pemfilePassword\此处
    是您从已安装的voip证书导出
    .pem
    文件时给出的密码。(请参阅第4点。)

  • yourDeviceTokenID\u生成的\u带有更新\u推送\u凭证\u带有令牌\u此处
    应替换为
    令牌
    ,令牌由
    PKPushRegistryDelegate
    方法生成。见下文

    func-pushRegistry(registry:PKPushRegistry,didUpdate-pushCredentials:PKPushCredentials,for-type:PKPushType){

  • 如果您有任何问题,请告诉我。我已经在前台、后台、锁屏应用程序上尝试并测试了此应用程序,甚至在从最近的应用程序中删除应用程序之后。
    (iOS 13.4.1和Xcode版本11.4(11E146))

    即使不是iOS 13,iOS也会终止应用程序。苹果自己说,如果应用程序是iOS 13及更高版本开发的,它会终止,但在报告失败后仍会终止应用程序。我已经与苹果开发人员支持人员谈过,他们说只有iOS 13会这样做,但我仍然有错误。

    你需要获得这些(必需的参数)在呼叫无效推送中。我不确定这是否是解决方案,当应用程序处于后台模式时,也不会收到带有这些参数的VoIP推送,因为必须报告呼叫,并且报告呼叫需要这些字段,因此您必须修改推送的有效负载。VoIP推送是否表示传入呼叫?如果是,则需要通过CallKit报告传入呼叫。如果没有,那么您必须使用正常的推送通知系统。我使用推送传入和推送呼叫,也使用voip类型,这两种类型都是正常推送。在这两种情况下,它们都不会以backgorund模式到达。唯一的方法是将不影响呼叫的呼叫作为正常推送进行管理。您认为这是解决方案吗IONS也适用于VoIP推送,这些推送不是推送呼叫,而是仅具有个性化负载的推送?您不能将VoIP推送用于
    let parts = pushCredentials.token.map { String(format: "%02.2hhx", $0) }
    
    let token = parts.joined()
    print("did update push credentials with token: \(token)") }