diff --git a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift index 4c5ab10..174bab5 100644 --- a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift +++ b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift @@ -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) {