The Feedback assistant number: FB16655952
Post
Replies
Boosts
Views
Activity
You can see the Apple Engineer's answer in https://developer.apple.com/forums/thread/774958
Yes? Why is it a problem to call it with "await"?
I don't know what the reason is. I suspect that the issue is caused by the asynchronous handling of "Task".
Because I compared the two reporting methods of CallKit and the reporting method of LiveCommunicationKit using code. When using the PushKit callback method func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void), only the block-based reporting method of CallKit successfully reports the VoIP. Both the async reporting methods of CallKit and LiveCommunicationKit encounter this issue in the background.
And I compared the two func receiveIncomingPush methods of PushKit, the async func receiveIncoming also encounters this issue in the background.
The only method that works successfully in all situations is calling the Completion block method of CallKit's reportIncoming.
What do you mean by "success rate" here? And which implementation is failing in the background case, "Task" or "await"?
"Success rate" means the voip report success rate in the background.
The await implementation is failed in the background case, Task always run successfully.
I don't know why that would be, but there maybe some additional entanglements with how async handling interact with GCD. In any case, the specific threads involved are not the issue, Task is. Using a private queue for this is fine.
Yes, and I found a Voice SDK's README, they also recommend a private queue to init the PKPushRegistry to avoid the failure.
The CallKit code is a sample report without Task, it is running correctly
I used Task for LiveCommunicationKit because the ConversationManager.reportIncomingNewConversation method can only be called with await.
And the success rate is relatively high when the app is not running, but it is highly likely to fail when the app is in the background.
if #available(iOS 17.4, *) {
var update = Conversation.Update(members: [Handle(type: .generic, value: callerName, displayName: callerName)])
update.capabilities = .playingTones
print("Received push")
Task {
print("LCKit Start Answer")
do {
try await LCKitManager.shared.reportNewIncomingConversation(uuid: uuid, update: update)
print("LCKit Answer Success")
completion()
} catch {
print(error)
completion()
}
}
} else {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .generic, value: callerName)
update.localizedCallerName = callerName
provider.reportNewIncomingCall(with: uuid, update: update) { _ in
completion()
}
}
If the issue is related to Task, it still reports error in the background even after I changed the PushKit delegate method to func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) async, it still reports errors in the background. It even doesn't print received push when the pushRegistry is init with main queue, and it prints received push and LCKit Start Answer when the pushRegistry is init with a custom queue.
If the application is not running, the
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) async {
print("received push")
if type != .voIP { return }
let dic = payload.dictionaryPayload
guard let uuidString = dic["uuid"] as? String,
let uuid = UUID(uuidString: uuidString),
let callerName = dic["callerName"] as? String else {
return
}
if #available(iOS 17.4, *) {
let update = Conversation.Update(members: [Handle(type: .generic, value: callerName, displayName: callerName)], capabilities: .playingTones)
try? await LCKitManager.shared.reportNewIncomingConversation(uuid: uuid, update: update)
}
}
After testing many times, the success rate of displaying the pop-up when the app is killed is relatively normal, with only occasional failures. However, the failure rate is very high when the app is in the background.
Moreover, when the app receives a VoIP notification and reports it while in the foreground, and then transitions to the background, the success rate of reporting the VoIP notification in the background is significantly increased.
In fact, the same processing logic works correctly in the background when using CallKit.
When I switch to LiveCommunicationKit, It also displays normally when the application in the foreground, this issue only occurs in the background.
And the console only prints "Received push" without "LCKit Start Answer"
let pushRegistry = PKPushRegistry(queue: .main)
if #available(iOS 17.4, *) {
var update = Conversation.Update(members: [Handle(type: .generic, value: callerName, displayName: callerName)])
update.capabilities = .playingTones
print("Received push")
// !!!!!!!
// Whatever I write `@MainActor in` or remove this code, Most of the time it's wrong when the app is in background
Task {
print("LCKit Start Answer")
do {
try await LCKitManager.shared.reportNewIncomingConversation(uuid: uuid, update: update)
print("LCKit Answer Success")
completion()
} catch {
print(error)
completion()
}
}
}
Console output:
Received push
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push.'
*** First throw call stack:
(0x1a6774f20 0x19e5f32b8 0x1a5c7b7f8 0x2191b09f8 0x1ae61add4 0x1ae62a2c4 0x2191afc60 0x1ae61913c 0x1ae61add4 0x1ae6295a4 0x1ae6291b8 0x1a6747710 0x1a6744914 0x1a6743cd8 0x1eb1951a8 0x1a8d7dae8 0x1a8e31d98 0x104faeb84 0x1c9f1b154)
libc++abi: terminating due to uncaught exception of type NSException
*** Assertion failure in -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes], PKPushRegistry.m:349
Assertion Stack:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push.'
*** First throw call stack:
(0x1a6774f20 0x19e5f32b8 0x1a5c7b7f8 0x2191b09f8 0x1ae61add4 0x1ae62a2c4 0x2191afc60 0x1ae61913c 0x1ae61add4 0x1ae6295a4 0x1ae6291b8 0x1a6747710 0x1a6744914 0x1a6743cd8 0x1eb1951a8 0x1a8d7dae8 0x1a8e31d98 0x1043927b8 0x1c9f1b154)
libc++abi: terminating due to uncaught exception of type NSException
Assertion failure in -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes], PKPushRegistry.m:349
I init the pushRegistry with main queue and use the method "func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) async", it crash immediately before the print "receive voip noti".
if I init the pushRegistry with a custom queue, it will show the print "receive voip noti", and crashed after the print "LCKit report start"
let pushRegistry = PKPushRegistry(queue: DispatchQueue(label: "LCKit", qos: .userInteractive))