From 5b5cdf1098d2926fdf5822885ce163f205b27f7f Mon Sep 17 00:00:00 2001 From: Sergei Date: Mon, 26 Jan 2026 13:25:19 -0800 Subject: [PATCH] Add audio output switcher for voice calls (Android speaker fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Audio button during active calls to switch output - Fallback to Speaker/Earpiece options when LiveKit API unavailable - Speaker now works correctly on Android 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/(tabs)/chat.tsx | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/app/(tabs)/chat.tsx b/app/(tabs)/chat.tsx index f018e3a..eba3d52 100644 --- a/app/(tabs)/chat.tsx +++ b/app/(tabs)/chat.tsx @@ -45,6 +45,7 @@ import { import { ConnectionState, Track } from 'livekit-client'; import { getToken, type BeneficiaryData } from '@/services/livekitService'; import { useAuth } from '@/contexts/AuthContext'; +import { getAvailableAudioOutputs, selectAudioOutput, setAudioOutput } from '@/utils/audioSession'; // Register LiveKit globals (must be called before using LiveKit) registerGlobals(); @@ -612,6 +613,40 @@ export default function ChatScreen() { endVoiceCallContext(); }, [endVoiceCallContext, callState.callDuration]); + // Audio output picker + const showAudioPicker = useCallback(async () => { + const devices = await getAvailableAudioOutputs(); + + // If devices found from LiveKit API, use them + if (devices.length > 0) { + const buttons: any[] = devices.map(device => ({ + text: device.name, + onPress: () => selectAudioOutput(device.id), + })); + buttons.push({ text: 'Cancel', style: 'cancel' }); + Alert.alert('Audio Output', 'Select audio device:', buttons); + return; + } + + // Fallback for Android (and iOS if no devices found) + // Show simple Speaker/Earpiece toggle using setAudioOutput() + Alert.alert( + 'Audio Output', + 'Select audio output:', + [ + { + text: '🔊 Speaker', + onPress: () => setAudioOutput(true), + }, + { + text: '📱 Earpiece', + onPress: () => setAudioOutput(false), + }, + { text: 'Cancel', style: 'cancel' }, + ] + ); + }, []); + // Handle voice transcript entries - add to chat in real-time const handleVoiceTranscript = useCallback((role: 'user' | 'assistant', text: string) => { if (!text.trim()) return; @@ -1025,6 +1060,15 @@ export default function ChatScreen() { )} + {/* Audio output button - only during active call */} + {isCallActive && ( + + + + )}