ios pushkit 在 reportnewIncommingCall 之前结束最后一次调用
ios pushkit end last call before reportnewIncommingCall
我卡在如何在报告新来电之前结束所有最后一次通话,我的功能适用于 2 个电话,这意味着我可以在报告新来电之前结束第一个电话
但问题是在next report之后,end call function throw error
这是我的代码:
// Handle incoming pushes
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
// print("Handle incoming pushes: \(payload.dictionaryPayload)")
endCall(thenReportNewCallForUuid: UUID.init())
}
func reportNewCall(uuid : UUID){
let config = CXProviderConfiguration(localizedName: "CallKitExample")
config.includesCallsInRecents = true
config.supportsVideo = true
config.supportedHandleTypes = [.generic]
config.iconTemplateImageData = UIImage(named: "logo_square")!.pngData()
config.maximumCallGroups = 1
config.maximumCallsPerCallGroup = 1
let provider = CXProvider(configuration: config)
provider.setDelegate(self, queue: nil)
let update = CXCallUpdate()
update.supportsHolding = false
update.supportsGrouping = false
update.supportsUngrouping = false
update.remoteHandle = CXHandle(type: .generic, value: uuid.uuidString)
update.hasVideo = true
provider.reportNewIncomingCall(with: uuid, update: update, completion: { error in
print("reportNewIncomingCall \(uuid) error: \(error)")
UserDefaults.standard.set(uuid.uuidString, forKey: "CallUUID")
UserDefaults.standard.synchronize()
})
}
func endCall(thenReportNewCallForUuid : UUID) {
guard let lastCallUUIDString = UserDefaults.standard.string(forKey: "CallUUID"), !lastCallUUIDString.isEmpty else{
return
}
print("end uuid: \(lastCallUUIDString)")
let call = UUID.init(uuidString: lastCallUUIDString)!
let controller = CXCallController()
let endTransaction = CXEndCallAction(call: call)
let transaction = CXTransaction(action: endTransaction)
controller.request(transaction, completion: { error in
if let error = error {
print("endcall Error: \(error)")
self.reportNewCall(uuid: thenReportNewCallForUuid)
} else {
print("endcall Success")
self.reportNewCall(uuid: thenReportNewCallForUuid)
}
})
}
这是我得到的日志 + 错误
end uuid: CB91CCC6-7FCD-49D3-BE93-7A6581295B57
endcall Error: Error Domain=com.apple.CallKit.error.requesttransaction Code=2 "(null)"
-> OK first time endcall error because no call
reportNewIncomingCall 202DB031-23AE-46B6-91E9-3FBA708E07A7 error: nil
end uuid: 202DB031-23AE-46B6-91E9-3FBA708E07A7
endcall Success -> Matched call to end -> success
reportNewIncomingCall C45FEC0B-1320-4357-ADEF-7B7CA28D96C8 error: nil
end uuid: C45FEC0B-1320-4357-ADEF-7B7CA28D96C8
endcall Error: Error Domain=com.apple.CallKit.error.requesttransaction Code=4 "(null)"
-> Matched call to end -> FAILED
reportNewIncomingCall CBDBA75A-B263-49E5-9138-8D5CCA28ED9E error: nil
有谁标出重复的请出示正确答案?谢谢
有人面临同样的问题吗?请帮忙
我至少在您的代码中发现了几个问题。但是,在此之前,为什么一接到新的来电就结束正在进行的通话?我只是好奇,因为它似乎不是一个很好的用户体验。
总之,我发现的问题如下:
- 在每次新来电时,您都会实例化一个新的
CXProvider
。如 documentation 中所述:
A VoIP app should create only one instance of CXProvider and store it for use globally.
- 您没有调用
pushRegistry(_:didReceiveIncomingPushWith:type:completion)
方法的完成处理程序。您应该在 reportNewIncomingCall(with:update:completion:)
方法的完成处理程序中调用它。
我认为您遇到的错误是由 CXProvider
问题引起的。但是,如果您不同时解决第二个问题,您可能会遇到另一个问题:系统会假设您没有报告新的来电,因此,在几次通话后,它将停止向您发送新的 VoIP 推送( this limitation 首次引入是在 iOS 13).
我遇到了同样的问题,并通过将 CXProvider、CXProfiderConfiguration 和 CXCallController 的实例化移到 pushRegistry 函数外部和 AppDelegate 的 didFinishLaunchingWithOptions 部分内部来解决它,如下所示:
private func voipRegistration() {
// Create a push registry object
let mainQueue = DispatchQueue.main
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [PKPushType.voIP]
config.iconTemplateImageData = #imageLiteral(resourceName: "cometchat_white").pngData()
config.includesCallsInRecents = false
config.ringtoneSound = "ringtone.caf"
config.supportsVideo = false
provider = CXProvider.init(configuration: config)
provider!.setDelegate(self, queue: nil)
}
您必须有一个 CXProvider 实例。
我卡在如何在报告新来电之前结束所有最后一次通话,我的功能适用于 2 个电话,这意味着我可以在报告新来电之前结束第一个电话
但问题是在next report之后,end call function throw error
这是我的代码:
// Handle incoming pushes
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
// print("Handle incoming pushes: \(payload.dictionaryPayload)")
endCall(thenReportNewCallForUuid: UUID.init())
}
func reportNewCall(uuid : UUID){
let config = CXProviderConfiguration(localizedName: "CallKitExample")
config.includesCallsInRecents = true
config.supportsVideo = true
config.supportedHandleTypes = [.generic]
config.iconTemplateImageData = UIImage(named: "logo_square")!.pngData()
config.maximumCallGroups = 1
config.maximumCallsPerCallGroup = 1
let provider = CXProvider(configuration: config)
provider.setDelegate(self, queue: nil)
let update = CXCallUpdate()
update.supportsHolding = false
update.supportsGrouping = false
update.supportsUngrouping = false
update.remoteHandle = CXHandle(type: .generic, value: uuid.uuidString)
update.hasVideo = true
provider.reportNewIncomingCall(with: uuid, update: update, completion: { error in
print("reportNewIncomingCall \(uuid) error: \(error)")
UserDefaults.standard.set(uuid.uuidString, forKey: "CallUUID")
UserDefaults.standard.synchronize()
})
}
func endCall(thenReportNewCallForUuid : UUID) {
guard let lastCallUUIDString = UserDefaults.standard.string(forKey: "CallUUID"), !lastCallUUIDString.isEmpty else{
return
}
print("end uuid: \(lastCallUUIDString)")
let call = UUID.init(uuidString: lastCallUUIDString)!
let controller = CXCallController()
let endTransaction = CXEndCallAction(call: call)
let transaction = CXTransaction(action: endTransaction)
controller.request(transaction, completion: { error in
if let error = error {
print("endcall Error: \(error)")
self.reportNewCall(uuid: thenReportNewCallForUuid)
} else {
print("endcall Success")
self.reportNewCall(uuid: thenReportNewCallForUuid)
}
})
}
这是我得到的日志 + 错误
end uuid: CB91CCC6-7FCD-49D3-BE93-7A6581295B57
endcall Error: Error Domain=com.apple.CallKit.error.requesttransaction Code=2 "(null)"
-> OK first time endcall error because no call
reportNewIncomingCall 202DB031-23AE-46B6-91E9-3FBA708E07A7 error: nil
end uuid: 202DB031-23AE-46B6-91E9-3FBA708E07A7
endcall Success -> Matched call to end -> success
reportNewIncomingCall C45FEC0B-1320-4357-ADEF-7B7CA28D96C8 error: nil
end uuid: C45FEC0B-1320-4357-ADEF-7B7CA28D96C8
endcall Error: Error Domain=com.apple.CallKit.error.requesttransaction Code=4 "(null)"
-> Matched call to end -> FAILED
reportNewIncomingCall CBDBA75A-B263-49E5-9138-8D5CCA28ED9E error: nil
有谁标出重复的请出示正确答案?谢谢
有人面临同样的问题吗?请帮忙
我至少在您的代码中发现了几个问题。但是,在此之前,为什么一接到新的来电就结束正在进行的通话?我只是好奇,因为它似乎不是一个很好的用户体验。
总之,我发现的问题如下:
- 在每次新来电时,您都会实例化一个新的
CXProvider
。如 documentation 中所述:
A VoIP app should create only one instance of CXProvider and store it for use globally.
- 您没有调用
pushRegistry(_:didReceiveIncomingPushWith:type:completion)
方法的完成处理程序。您应该在reportNewIncomingCall(with:update:completion:)
方法的完成处理程序中调用它。
我认为您遇到的错误是由 CXProvider
问题引起的。但是,如果您不同时解决第二个问题,您可能会遇到另一个问题:系统会假设您没有报告新的来电,因此,在几次通话后,它将停止向您发送新的 VoIP 推送( this limitation 首次引入是在 iOS 13).
我遇到了同样的问题,并通过将 CXProvider、CXProfiderConfiguration 和 CXCallController 的实例化移到 pushRegistry 函数外部和 AppDelegate 的 didFinishLaunchingWithOptions 部分内部来解决它,如下所示:
private func voipRegistration() {
// Create a push registry object
let mainQueue = DispatchQueue.main
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [PKPushType.voIP]
config.iconTemplateImageData = #imageLiteral(resourceName: "cometchat_white").pngData()
config.includesCallsInRecents = false
config.ringtoneSound = "ringtone.caf"
config.supportsVideo = false
provider = CXProvider.init(configuration: config)
provider!.setDelegate(self, queue: nil)
}
您必须有一个 CXProvider 实例。