Fix iOS build: use LiveKit 2.15.3 audio API (drop nonexistent setEngineAvailability)

The build failed: 'AudioManager' has no member 'setEngineAvailability' — that API
is only on unreleased/main docs, not in the resolved LiveKitClient 2.15.3. Use the
API that actually ships (per audio.md): disable LiveKit's automatic AVAudioSession
configuration (AudioManager.shared.audioSession.isAutomaticConfigurationEnabled =
false) and configure the session ourselves in CXProvider didActivate. Removed all
setEngineAvailability(.none/.default) calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 18:24:54 +05:30
parent 36edc6de12
commit c472ee2618
2 changed files with 12 additions and 11 deletions
@@ -18,8 +18,9 @@ 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 (AudioManager.setEngineAvailability on didActivate/didDeactivate), which the
# WebView's WebRTC could not do. Pulls in the WebRTC binary transitively.
# 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'
@@ -55,12 +55,12 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega
registry.desiredPushTypes = [.voIP]
pushRegistry = registry
// CallKit audio coordination. LiveKit auto-configures & activates the AVAudioSession by default, which
// RACES CallKit's own activation intermittent dead mic / no audio, and the output route only settling
// once audio starts flowing (the "speaker turns on late" symptom). Fix (per LiveKit's CallKit guide):
// disable auto-config, keep the audio engine OFF, and start it ONLY inside CXProvider didActivate.
// CallKit audio coordination. LiveKit auto-configures the AVAudioSession by default, which RACES
// CallKit's own activation intermittent dead mic / no audio + the output route only settling once
// audio starts flowing (the "speaker turns on late" symptom). Fix (per LiveKit's audio.md): turn OFF
// LiveKit's automatic session configuration and configure the session ourselves in CXProvider
// didActivate (when CallKit hands us the active session).
AudioManager.shared.audioSession.isAutomaticConfigurationEnabled = false
try? AudioManager.shared.setEngineAvailability(.none)
}
// MARK: - LiveKit media
@@ -291,19 +291,19 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega
action.fulfill()
}
// CallKit owns the AVAudioSession lifecycle. Configure the session and START LiveKit's audio engine ONLY
// here (never before) this is the fix for the intermittent dead mic / no-audio and late speaker routing.
// CallKit owns the AVAudioSession lifecycle. Since we disabled LiveKit's automatic configuration, configure
// the session HERE, when CallKit activates it this is the fix for the intermittent dead mic / no-audio
// and late speaker routing (LiveKit's audio engine then runs on a correctly-configured, active session).
// Note: don't call setActive(true) CallKit already activated it.
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)])
}
}
public func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
try? AudioManager.shared.setEngineAvailability(.none) // stop the engine until the next call's didActivate
notifyListeners("audioDeactivated", data: ["ok": true])
}
}