fix(ios): keep CallKit call active on answer so the app foregrounds

Answering did not open the app: ending the CallKit call immediately (to free the mic)
made iOS cancel the app launch before it foregrounded. Keep the call ACTIVE on answer
— fulfilling an active-call answer is what foregrounds/unlocks the app — and fire the
answerCall event so the WebView joins. didActivate stays a no-op (don't fight WebKit's
mic). The CallKit call is ended later when the WebView call ends.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 20:44:09 +05:30
parent 6096b62368
commit 9dc253143e
@@ -175,16 +175,12 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega
var data: [String: Any] = calls[uuid] ?? [:]
data["callUUID"] = uuid.uuidString
action.fulfill()
// RING-ONLY MODEL: CallKit was used purely for the incoming ring. End the CallKit call NOW so iOS
// RELEASES the microphone an active CallKit call reserves the mic and the WebView's WebRTC would get
// a dead mic. Then hand the call to the WebView, giving iOS a beat to tear down the CallKit audio
// session before the WebView grabs the mic. Background audio is preserved by the 'voip' background mode.
provider.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded)
calls.removeValue(forKey: uuid)
endedCalls.insert(uuid)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
self?.notifyListeners("answerCall", data: data)
}
// Keep the CallKit call ACTIVE fulfilling the answer for an ACTIVE call is what foregrounds/unlocks
// the app and gives it in-call context (ending it here made iOS cancel the app launch the app never
// opened). The WebView carries the media; we deliberately do NOT reconfigure the audio session
// (didActivate is a no-op) so we don't fight WebKit's WebRTC mic. The CallKit call is ended later when
// the WebView call ends (the dm-call/group-call inactive event JS calls endCall()).
notifyListeners("answerCall", data: data)
}
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {