Fix crash after multiple calls: always reportNewIncomingCall for every VoIP push

iOS 13+ terminates the app if a PushKit VoIP push doesn't call reportNewIncomingCall
before completion(). My earlier "no re-ring blip" change made the cancel handler SKIP
the report for already-known/ended calls — which is exactly what iOS kills the app
for, surfacing as a crash after several calls (a cancel push for a prior call's UUID).
Revert to ALWAYS report then immediately end: for a still-active/ringing UUID the
report errors harmlessly (no second ring) and reportCall ends it; only a late duplicate
cancel shows a brief, unavoidable blip. A crash is far worse than a blip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 13:09:25 +05:30
parent f4dbbde558
commit fafc480904
@@ -211,27 +211,21 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega
// reporting a NEW incoming call is what caused the "rings back for a second" blip on a call we've
// already handled. So:
if (dict["type"] as? String) == "cancel" {
// (a) already ended here nothing to do (re-reporting would blip).
if endedCalls.contains(uuid) { completion(); return }
// (b) a call we already know (still ringing OR active) end it WITHOUT reporting a new incoming,
// so there's no blip. reportCall(endedAt:) cleanly dismisses the CallKit UI.
if calls[uuid] != nil || activeUUID == uuid {
var ev = calls[uuid] ?? [:]; ev["callUUID"] = uuid.uuidString
calls.removeValue(forKey: uuid)
endedCalls.insert(uuid)
if activeUUID == uuid { disconnectRoom(); activeUUID = nil }
provider?.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded)
notifyListeners("endCall", data: ev) // if it was active, leave the meeting window too
completion()
return
}
// (c) unknown call (this very push relaunched the app) we MUST report, then immediately end.
// A tiny unavoidable blip, but only in this rare cold case.
// iOS 13+ TERMINATES the app if a VoIP push doesn't result in reportNewIncomingCall before
// completion() that's the crash after several calls (my earlier "no-blip" optimization SKIPPED
// the report for known/ended calls, which iOS kills for). So ALWAYS report, then immediately end:
// * uuid already ringing/active the report errors harmlessly (NO second ring), reportCall ends it.
// * late/duplicate cancel (done) a brief, unavoidable blip (acceptable; a crash is not).
let u = CXCallUpdate()
u.remoteHandle = CXHandle(type: .generic, value: (dict["callerName"] as? String) ?? "Call")
let wasActive = (activeUUID == uuid)
var ev = calls[uuid] ?? [:]; ev["callUUID"] = uuid.uuidString
calls.removeValue(forKey: uuid)
endedCalls.insert(uuid)
if wasActive { disconnectRoom(); activeUUID = nil }
provider?.reportNewIncomingCall(with: uuid, update: u) { [weak self] _ in
self?.provider?.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded)
if wasActive { self?.notifyListeners("endCall", data: ev) } // active call cancelled leave the meeting
completion()
}
return