diff --git a/utils/audioSession.ts b/utils/audioSession.ts index 9ba9f6d..efec804 100644 --- a/utils/audioSession.ts +++ b/utils/audioSession.ts @@ -50,32 +50,76 @@ export async function configureAudioForVoiceCall(): Promise { } if (Platform.OS === 'ios') { - // iOS-specific configuration - // IMPORTANT: Use 'videoChat' mode instead of 'voiceChat' to enable speaker by default - // voiceChat + defaultToSpeaker causes OSStatus error -50 on some iOS versions - console.log('[AudioSession] Step 1: Setting Apple audio config...'); - await AudioSession.setAppleAudioConfiguration({ - audioCategory: 'playAndRecord', - // Only use options that are safe with playAndRecord category - // Removed 'defaultToSpeaker' - it conflicts with some iOS versions - // Instead, using 'videoChat' mode which defaults to speaker - audioCategoryOptions: [ - 'allowBluetooth', - 'mixWithOthers', - ], - // Use 'videoChat' instead of 'voiceChat' - it enables speaker by default - audioMode: 'videoChat', - }); + // iOS-specific configuration with fallback strategies + // Try multiple configurations in order of preference - console.log('[AudioSession] Step 2: Starting audio session...'); + const configs = [ + // Strategy 1: videoChat mode (speaker by default, no problematic options) + { + name: 'videoChat', + config: { + audioCategory: 'playAndRecord', + audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'], + audioMode: 'videoChat', + }, + }, + // Strategy 2: voiceChat mode (more compatible, but earpiece by default) + { + name: 'voiceChat', + config: { + audioCategory: 'playAndRecord', + audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'], + audioMode: 'voiceChat', + }, + }, + // Strategy 3: Minimal config (most compatible) + { + name: 'minimal', + config: { + audioCategory: 'playAndRecord', + audioCategoryOptions: [], + audioMode: 'default', + }, + }, + ]; + + let configSuccess = false; + let lastError: any = null; + + for (const { name, config } of configs) { + try { + console.log(`[AudioSession] Trying ${name} configuration...`); + await AudioSession.setAppleAudioConfiguration(config); + console.log(`[AudioSession] ${name} configuration succeeded!`); + configSuccess = true; + break; + } catch (err) { + console.warn(`[AudioSession] ${name} config failed:`, err); + lastError = err; + // Continue to next strategy + } + } + + if (!configSuccess) { + console.error('[AudioSession] All iOS configurations failed!'); + throw lastError || new Error('All audio configurations failed'); + } + + console.log('[AudioSession] Starting audio session...'); await AudioSession.startAudioSession(); - console.log('[AudioSession] Step 3: Setting default output to speaker...'); - await AudioSession.configureAudio({ - ios: { - defaultOutput: 'speaker', - }, - }); + // Try to set speaker output (non-critical, don't throw on failure) + try { + console.log('[AudioSession] Setting default output to speaker...'); + await AudioSession.configureAudio({ + ios: { + defaultOutput: 'speaker', + }, + }); + } catch (outputErr) { + console.warn('[AudioSession] Could not set speaker output:', outputErr); + // Continue anyway - audio will work, just maybe on earpiece + } } else if (Platform.OS === 'android') { // Android-specific configuration // IMPORTANT: Using 'music' stream type to force output to speaker