From c3de5ac8e3b8a90bfe2300e7cadc834925d38857 Mon Sep 17 00:00:00 2001 From: sravan Date: Fri, 31 Jul 2026 19:35:57 +0530 Subject: [PATCH] Revert "Native calls: upgrade to LiveKit 2.15 + add CallKit audio-session coordination" This reverts commit 455d16abccb6cce771387af102d1c2225c1178c4. --- codemagic.yaml | 4 +-- mobile/plugins/native-call/NativeCall.podspec | 10 +++---- .../NativeCallPlugin/NativeCallPlugin.swift | 27 +++++-------------- 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/codemagic.yaml b/codemagic.yaml index c016d6a..d44b10f 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -93,9 +93,7 @@ workflows: - name: Install CocoaPods script: | cd mobile/ios/App - # --repo-update refreshes the CocoaPods spec repo so it knows the latest LiveKitClient (the build box's - # cached spec repo was stale, so '~> 2.x' resolved an OLD version missing the CallKit audio API). - pod install --repo-update + pod install - name: Build the signed IPA script: | diff --git a/mobile/plugins/native-call/NativeCall.podspec b/mobile/plugins/native-call/NativeCall.podspec index ad73776..ccbc86b 100644 --- a/mobile/plugins/native-call/NativeCall.podspec +++ b/mobile/plugins/native-call/NativeCall.podspec @@ -18,12 +18,10 @@ Pod::Spec.new do |s| s.ios.deployment_target = '14.0' s.dependency 'Capacitor' # LiveKit iOS SDK — carries the call media NATIVELY so audio survives backgrounding AND coordinates with - # CallKit's audio session (auto-config OFF via AudioManager.shared.audioSession.isAutomaticConfigurationEnabled - # + setEngineAvailability in CXProvider didActivate/didDeactivate), which the WebView's WebRTC could not do. - # Pulls in the WebRTC binary transitively. PINNED to 2.15+: the CallKit audio-session coordination API - # (AudioManager.audioSession / setEngineAvailability) only exists in 2.15+, and '~> 2.0' was resolving an - # older 2.x on the build box (see the `pod install --repo-update` in codemagic.yaml). - s.dependency 'LiveKitClient', '~> 2.15' + # CallKit's audio session (auto-config OFF via AudioManager.shared.audioSession.isAutomaticConfigurationEnabled; + # we configure the session in CXProvider didActivate), which the WebView's WebRTC could not do. Pulls in the + # WebRTC binary transitively. + s.dependency 'LiveKitClient', '~> 2.0' # CallKit + PushKit + AVFoundation are system frameworks (no external pod). s.frameworks = 'CallKit', 'PushKit', 'AVFoundation' s.swift_version = '5.1' diff --git a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift index 23e88a6..0e794aa 100644 --- a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift +++ b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift @@ -54,21 +54,16 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega registry.delegate = self registry.desiredPushTypes = [.voIP] pushRegistry = registry - // CallKit audio coordination (needs LiveKit 2.15+, pinned in NativeCall.podspec). LiveKit's automatic - // AVAudioSession configuration RACES CallKit's own activation → intermittent dead mic / no audio + the - // output route only settling once audio flows ("speaker turns on late"). Fix: turn auto-config OFF and - // keep the audio engine OFF; we configure the session and enable the engine ONLY in didActivate. - AudioManager.shared.audioSession.isAutomaticConfigurationEnabled = false - try? AudioManager.shared.setEngineAvailability(.none) + // NOTE: the CallKit↔LiveKit audio-session coordination (AudioManager.audioSession / + // setEngineAvailability) needs LiveKit 2.15+, but the build currently resolves an older 2.x that lacks + // those symbols. So we rely on LiveKit's default audio handling for now and only configure the session + // with plain AVFoundation in didActivate. Revisit once the pod is pinned/upgraded to 2.15+. } // MARK: - LiveKit media private func connectRoom(url: String, token: String) { guard !url.isEmpty, !token.isEmpty else { return } - // Ask for mic permission now (we still connect MUTED). If it stays "undetermined", enabling the audio - // engine in didActivate can block on first use — determining it up front avoids that. - AVAudioSession.sharedInstance().requestRecordPermission { _ in } let old = room let r = Room() room = r @@ -290,20 +285,12 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega action.fulfill() } - // CallKit owns the AVAudioSession lifecycle. Since LiveKit auto-config is OFF, configure the session HERE — - // when CallKit activates it — and enable LiveKit's audio engine. This is the fix for the intermittent - // dead mic / no-audio and late speaker routing. Don't call setActive(true): CallKit already activated it. + // Keep the last known-good audio behavior (rely on LiveKit's default session handling). We only report the + // state to JS. The proper CallKit↔LiveKit session coordination is deferred until the pod is on 2.15+. public func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { - do { - try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.mixWithOthers]) - try AudioManager.shared.setEngineAvailability(.default) - notifyListeners("audioActivated", data: ["ok": true]) - } catch { - notifyListeners("audioActivated", data: ["ok": false, "error": String(describing: error)]) - } + notifyListeners("audioActivated", data: ["ok": true]) } public func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { - try? AudioManager.shared.setEngineAvailability(.none) // keep the engine off until the next call activates notifyListeners("audioDeactivated", data: ["ok": true]) } }