diff --git a/utils/audioSession.ts b/utils/audioSession.ts index 48101f2..9ba9f6d 100644 --- a/utils/audioSession.ts +++ b/utils/audioSession.ts @@ -51,29 +51,31 @@ 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', - // Note: removed 'allowBluetoothA2DP' - it's incompatible with playAndRecord - // on some iOS versions and causes "status -50" error. - // 'allowBluetooth' (HFP profile) is sufficient for voice calls. + // 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', - 'defaultToSpeaker', 'mixWithOthers', ], - audioMode: 'voiceChat', + // Use 'videoChat' instead of 'voiceChat' - it enables speaker by default + audioMode: 'videoChat', }); - console.log('[AudioSession] Step 2: Setting default output...'); + console.log('[AudioSession] Step 2: Starting audio session...'); + await AudioSession.startAudioSession(); + + console.log('[AudioSession] Step 3: Setting default output to speaker...'); await AudioSession.configureAudio({ ios: { defaultOutput: 'speaker', }, }); - - console.log('[AudioSession] Step 3: Starting audio session...'); - await AudioSession.startAudioSession(); } else if (Platform.OS === 'android') { // Android-specific configuration // IMPORTANT: Using 'music' stream type to force output to speaker @@ -154,18 +156,15 @@ export async function reconfigureAudioForPlayback(): Promise { } if (Platform.OS === 'ios') { - // Just reconfigure the same settings - this "refreshes" the audio routing + // Reconfigure with same safe settings - this "refreshes" the audio routing await AudioSession.setAppleAudioConfiguration({ audioCategory: 'playAndRecord', - // Note: removed 'allowBluetoothA2DP' - it's incompatible with playAndRecord - // on some iOS versions and causes "status -50" error. - // 'allowBluetooth' (HFP profile) is sufficient for voice calls. audioCategoryOptions: [ 'allowBluetooth', - 'defaultToSpeaker', 'mixWithOthers', ], - audioMode: 'voiceChat', + // Use 'videoChat' - defaults to speaker + audioMode: 'videoChat', }); } else if (Platform.OS === 'android') { // Reconfigure Android audio to ensure speaker output @@ -209,22 +208,20 @@ export async function setAudioOutput(useSpeaker: boolean): Promise { } if (Platform.OS === 'ios') { - // iOS: Configure audio output + // iOS: Update configuration based on desired output + // Use 'videoChat' mode for speaker, 'voiceChat' for earpiece + await AudioSession.setAppleAudioConfiguration({ + audioCategory: 'playAndRecord', + audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'], + audioMode: useSpeaker ? 'videoChat' : 'voiceChat', + }); + + // Also set default output await AudioSession.configureAudio({ ios: { defaultOutput: useSpeaker ? 'speaker' : 'earpiece', }, }); - - // Also update the full configuration to ensure it takes effect - // Note: removed 'allowBluetoothA2DP' - causes "status -50" error - await AudioSession.setAppleAudioConfiguration({ - audioCategory: 'playAndRecord', - audioCategoryOptions: useSpeaker - ? ['allowBluetooth', 'defaultToSpeaker', 'mixWithOthers'] - : ['allowBluetooth', 'mixWithOthers'], - audioMode: 'voiceChat', - }); } else if (Platform.OS === 'android') { // Android: Switch stream type to control speaker/earpiece // - 'music' stream goes to speaker by default