### Install Dependencies and Run App Source: https://github.com/livekit-examples/agent-starter-react-native/blob/main/README.md After cloning the template, install project dependencies using npm and then run the application for Android or iOS using Expo. ```bash npm install ``` ```bash # Android npx expo run:android ``` ```bash # iOS npx expo run:ios ``` -------------------------------- ### Bootstrap App with LiveKit CLI Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Use the LiveKit CLI to create the project and link it to your sandbox token server. Install dependencies and run the app on Android or iOS. ```bash # Create the project and link it to your sandbox token server lk app create --template agent-starter-react-native --sandbox # Install dependencies npm install # Run on Android npx expo run:android # Run on iOS npx expo run:ios ``` -------------------------------- ### Manage Audio Session in Assistant Screen Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Starts the native audio session on mount and stops it on unmount using `AudioSession.startAudioSession()` and `AudioSession.stopAudioSession()`. This must be done before any audio capture or playback. ```tsx import { AudioSession, useIOSAudioManagement, useRoomContext } from '@livekit/react-native'; import { useEffect } from 'react'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function AssistantScreen() { // Must start the audio session before any audio capture/playback useEffect(() => { AudioSession.startAudioSession(); return () => { AudioSession.stopAudioSession(); }; }, []); return ( ); } function RoomView() { const room = useRoomContext(); // Manages iOS audio route changes (speaker/earpiece/Bluetooth) automatically useIOSAudioManagement(room, true /* preferSpeaker */); // ... rest of room UI } ``` -------------------------------- ### AgentVisualization Component for Agent Display Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Displays the AI agent's audio visualization and optionally their video track. It uses the useAgent hook to get agent state and media tracks. ```tsx import AgentVisualization from '@/app/assistant/ui/AgentVisualization'; import { Animated } from 'react-native'; // Placed as an absolutely-positioned animated view that expands/collapses // based on whether the chat panel is open ``` -------------------------------- ### Clone and Initialize LiveKit Agent Template Source: https://github.com/livekit-examples/agent-starter-react-native/blob/main/README.md Use the LiveKit CLI to clone this template and connect it to your LiveKit Cloud sandbox. Ensure you have your sandbox ID from LiveKit Cloud settings. ```bash lk app create --template agent-starter-react-native --sandbox ``` -------------------------------- ### Configure Connection Details Manually Source: https://github.com/livekit-examples/agent-starter-react-native/blob/main/README.md If not using the LiveKit CLI, manually edit the `hooks/useConnectionDetails.ts` file to provide your `sandboxID` or a custom token server URL and token. ```typescript edit the `hooks/useConnectionDetails.ts` file to add either a `sandboxID` (from your project's **Options** on the [Settings](https://cloud.livekit.io/projects/p_/settings/project) page), or a [manually generated](#token-generation) URL and token. ``` -------------------------------- ### Media Controls with `useLocalParticipant` and `useTrackToggle` Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Exposes local participant's track state and provides toggle functions for microphone, camera, and screen share. `useTrackToggle` manages the enabled state and toggle function for a specific media track source. ```tsx import { useLocalParticipant, useParticipantTracks, } from '@livekit/react-native'; import { useTrackToggle } from '@livekit/components-react'; import { Track } from 'livekit-client'; function RoomView() { const { isMicrophoneEnabled, isCameraEnabled, isScreenShareEnabled, cameraTrack: localCameraTrack, localParticipant, } = useLocalParticipant(); // Each toggle hook manages a specific media track const micToggle = useTrackToggle({ source: Track.Source.Microphone }); const cameraToggle = useTrackToggle({ source: Track.Source.Camera }); const screenShareToggle = useTrackToggle({ source: Track.Source.ScreenShare }); // Pass toggle functions to the ControlBar return ( void isCameraEnabled, onCameraClick: cameraToggle.toggle, isScreenShareEnabled, onScreenShareClick: screenShareToggle.toggle, isChatEnabled: false, onChatClick: () => {}, onExitClick: () => {}, }} /> ); } ``` -------------------------------- ### ControlBar Component for Media Toggles Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Renders buttons for microphone, camera, screen share, chat, and exit. The microphone button includes a live BarVisualizer for audio feedback. Active states are highlighted. ```tsx import ControlBar from '@/app/assistant/ui/ControlBar'; micToggle.toggle(), isCameraEnabled: false, // Shows camera-off icon onCameraClick: () => cameraToggle.toggle(), isScreenShareEnabled: false, // Shows screen-share-off icon onScreenShareClick: () => screenShareToggle.toggle(), isChatEnabled: true, // Shows chat-on icon, highlighted onChatClick: () => setChatEnabled(v => !v), onExitClick: () => { connection.disconnect(); router.back(); }, }} /> // BarVisualizer inside mic button: barCount=3, barColor='#CCCCCC', barWidth=2 ``` -------------------------------- ### Expo app.json Configuration for Android and iOS Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Configures the Expo app, including Android permissions for audio/video, LiveKit and WebRTC plugins, and dark UI style. ```json { "expo": { "name": "voice-assistant-react-native", "slug": "voice-assistant-react-native", "version": "1.0.0", "userInterfaceStyle": "dark", "newArchEnabled": true, "ios": { "bundleIdentifier": "io.livekit.voiceassistantreactnative", "bitcode": false }, "android": { "package": "io.livekit.voiceassistantreactnative", "permissions": [ "android.permission.RECORD_AUDIO", "android.permission.CAMERA", "android.permission.INTERNET", "android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.BLUETOOTH" ] }, "plugins": [ "expo-router", "@livekit/react-native-expo-plugin", // Required for LiveKit native modules "@config-plugins/react-native-webrtc" // Required for WebRTC support ], "experiments": { "typedRoutes": true } } } ``` -------------------------------- ### ConnectionProvider for Session State Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Wraps the app to provide shared LiveKit session state using `useSession` from `@livekit/components-react`. Manages the LiveKit session lifecycle and exposes `connect`/`disconnect` actions and `isConnectionActive` flag. Supports sandbox token servers or hardcoded credentials. ```tsx // hooks/useConnection.tsx import { TokenSource, TokenSourceResponseObject } from 'livekit-client'; import { createContext, useContext, useMemo, useState } from 'react'; import { SessionProvider, useSession } from '@livekit/components-react'; // Option A: LiveKit Cloud sandbox token server const sandboxID = 'your-sandbox-id-here'; const agentName = 'my-agent'; // optional: dispatch a specific named agent // Option B: Hardcoded credentials (for testing only) const hardcodedUrl = 'wss://your-project.livekit.cloud'; const hardcodedToken = 'eyJhbGciOiJIUzI1NiIsInR5...'; export function ConnectionProvider({ children }: { children: React.ReactNode }) { const [isConnectionActive, setIsConnectionActive] = useState(false); const tokenSource = useMemo(() => { if (sandboxID) { return TokenSource.sandboxTokenServer(sandboxID); } return TokenSource.literal({ serverUrl: hardcodedUrl, participantToken: hardcodedToken, } satisfies TokenSourceResponseObject); }, []); const session = useSession(tokenSource, agentName ? { agentName } : undefined); const { start: startSession, end: endSession } = session; const value = useMemo(() => ({ isConnectionActive, connect: () => { setIsConnectionActive(true); startSession(); }, disconnect: () => { setIsConnectionActive(false); endSession(); }, }), [startSession, endSession, isConnectionActive]); return ( {children} ); } ``` -------------------------------- ### Consume Connection Context with `useConnection` Hook Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Use this hook inside a `ConnectionProvider` to access connection status and callbacks. It throws an error if used outside the provider. ```tsx import { useConnection } from '@/hooks/useConnection'; import { useRouter } from 'expo-router'; import { useEffect } from 'react'; import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native'; export default function StartScreen() { const router = useRouter(); const { isConnectionActive, connect } = useConnection(); // Auto-navigate to the assistant screen once connection is active useEffect(() => { if (isConnectionActive) { router.navigate('../assistant'); } }, [isConnectionActive, router]); return ( Chat live with your voice AI agent connect()} disabled={isConnectionActive} style={{ backgroundColor: '#002CF2', borderRadius: 24, padding: 12, minWidth: 200 }} > {isConnectionActive && } {isConnectionActive ? 'Connecting...' : 'Start Voice Assistant'} ); } ``` -------------------------------- ### Initialize LiveKit React Native Globals Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Call `registerGlobals()` once at the app root before using any LiveKit components or hooks. This registers required WebRTC globals for the React Native environment. ```tsx // app/_layout.tsx import { registerGlobals } from '@livekit/react-native'; import { Stack } from 'expo-router'; import { ConnectionProvider } from '@/hooks/useConnection'; import { useColorScheme } from '@/hooks/useColorScheme'; import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; // Called once at the module level — required before any LiveKit hook/component registerGlobals(); export default function RootLayout() { const colorScheme = useColorScheme(); return ( ); } ``` -------------------------------- ### Use Session Messages for Chat and Transcription Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Hook to access chat messages and a send function for the current LiveKit session. Use this to display both user-sent text and AI agent transcriptions. ```tsx import { useSessionMessages } from '@livekit/components-react'; import { useCallback, useState } from 'react'; function RoomView() { const { messages, send } = useSessionMessages(); const [chatMessage, setChatMessage] = useState(''); const onChatSend = useCallback( (message: string) => { send(message); // Sends a text message into the LiveKit session setChatMessage(''); // Clears the input }, [send] ); return ( <> {/* Renders the full conversation — both user and agent messages * /} {/* Text input component wired to onChatSend * /} ); } ``` -------------------------------- ### useThemeColor Hook for Theme-Aware Colors Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Resolves color values from the Colors constant, respecting the current light/dark color scheme. Accepts per-prop overrides for themes and falls back to the global palette. ```ts import { useThemeColor } from '@/hooks/useThemeColor'; function MyComponent() { // Uses Colors.light.background or Colors.dark.background depending on scheme const bg = useThemeColor({}, 'background'); // Override only the light theme color; dark falls back to Colors.dark.tint const tint = useThemeColor({ light: '#ff6600' }, 'tint'); return ; } // Colors palette (constants/Colors.ts): // light: { text: '#11181C', background: '#fff', tint: '#0a7ea4', icon: '#687076' } // dark: { text: '#ECEDEE', background: '#151718', tint: '#fff', icon: '#9BA1A6' } ``` -------------------------------- ### ChatLog Component for Conversation Display Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt Component to render a scrollable list of messages. It differentiates between local participant messages (right-aligned) and agent messages (left-aligned) and adapts to theme colors. ```tsx import ChatLog from '@/app/assistant/ui/ChatLog'; import { ReceivedMessage } from '@livekit/components-react'; // Example messages array shape const messages: ReceivedMessage[] = [ { id: '1', message: 'Hello, how can I help you today?', from: agentParticipant, timestamp: Date.now() }, { id: '2', message: 'What is the weather like?', from: localParticipant, timestamp: Date.now() }, ]; // Usage in parent component ``` -------------------------------- ### ChatBar Component for Text Input Source: https://context7.com/livekit-examples/agent-starter-react-native/llms.txt A text input component wrapped in KeyboardAvoidingView for composing and sending messages. It handles keyboard offsets and calls the provided onChatSend callback. ```tsx import ChatBar from '@/app/assistant/ui/ChatBar'; import { useState } from 'react'; function MyScreen() { const [message, setMessage] = useState(''); return ( { console.log('Sending:', text); // e.g. "What is the weather?" setMessage(''); }} // iOS: behavior="padding", Android: behavior="height" // keyboardVerticalOffset={24} /> ); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.