Embed React Native SDK Integration Guide
Overview
The Embed React Native SDK is a powerful voice-enabled AI agent library that provides real-time communication capabilities. This comprehensive guide will walk you through the complete integration process from installation to deployment.
Prerequisites
- Node.js 18+
- React Native 0.74 or higher
- Platform specific:
This SDK requires proper setup of audio permissions and real-time communication dependencies.
Installation
Install the Embed React Native SDK using your preferred package manager:
npm install @revrag-ai/embed-react-native
Peer Dependencies
The SDK requires several peer dependencies to be installed in your project. Install all required dependencies:
# Install peer dependencies
npm install @livekit/react-native @livekit/react-native-webrtc
npm install @react-native-async-storage/async-storage
npm install react-native-gesture-handler react-native-reanimated
npm install react-native-linear-gradient lottie-react-native
npm install react-native-safe-area-context
# For iOS, run pod install
cd ios && pod install && cd ..
Android Configuration
1. Android Manifest Permissions
Add the following permissions to your android/app/src/main/AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required permissions for Embed SDK -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Add the following permissions for embed -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MICROPHONE" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:hardwareAccelerated="true"
>
<!-- Your activities and other components -->
</application>
</manifest>
2. Build.gradle Configuration
Add Lottie dependency to your android/app/build.gradle
:
dependencies {
implementation 'com.airbnb.android:lottie:6.0.1'
// ... other dependencies
}
3. ProGuard Configuration
If you’re using ProGuard, add these rules to your android/app/proguard-rules.pro
:
# Embed SDK
-keep class com.revrag.embed.** { *; }
-keep class org.webrtc.** { *; }
-dontwarn org.webrtc.**
# Lottie
-keep class com.airbnb.lottie.** { *; }
iOS Configuration
1. iOS Permissions
CRITICAL: Add the following permissions to your ios/YourAppName/Info.plist
. Missing NSMicrophoneUsageDescription
will cause the app to crash when accessing the microphone.
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to microphone for voice communication with AI agent</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
2. Pod Installation
After installing peer dependencies, run:
3. iOS Build Settings
If you encounter build issues, update your iOS project settings in ios/YourAppName/Info.plist
:
- Enable Bitcode:
NO
- Build Active Architecture Only:
YES
(for Debug)
Babel Configuration
CRITICAL: React Native Reanimated requires specific Babel configuration. The reanimated plugin must be the last plugin in the plugins array.
Add the React Native Reanimated plugin to your babel.config.js
:
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
// ... other plugins
'react-native-reanimated/plugin', // ← This MUST be the last plugin
],
};
After updating babel.config.js
, clean your project cache:
npx react-native start --reset-cache
SDK Initialization
useInitialize Hook
Initialize the SDK at the root level of your application using the useInitialize
hook:
import { useInitialize } from '@revrag-ai/embed-react-native';
function App() {
const { isInitialized, error } = useInitialize({
apiKey: 'YOUR_API_KEY',
embedUrl: 'YOUR_EMBED_SERVER_URL',
});
if (error) {
console.error('SDK initialization failed:', error);
}
if (!isInitialized) {
// Show loading screen while initializing
return <LoadingScreen />;
}
// Your app components
return <YourApp />;
}
Configuration Options
Property | Type | Required | Description |
---|
apiKey | string | ✅ | Your Embed API key |
embedUrl | string | ✅ | Your Embed server URL |
App Setup
1. Wrap App with GestureHandlerRootView
You must wrap your entire app with GestureHandlerRootView
for the SDK to work properly.
import React from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useInitialize } from '@revrag-ai/embed-react-native';
export default function App() {
const { isInitialized, error } = useInitialize({
apiKey: 'your_api_key_here',
embedUrl: 'https://your-embed-server.com',
});
return (
<GestureHandlerRootView style={{ flex: 1 }}>
{/* Your app components */}
</GestureHandlerRootView>
);
}
Add the floating voice agent button to your screen:
import { EmbedButton } from '@revrag-ai/embed-react-native';
function MyScreen() {
return (
<View style={{ flex: 1 }}>
{/* Your screen content */}
<EmbedButton />
</View>
);
}
Event System
The SDK provides a powerful event system for sending user context and application state to the AI agent.
Available Events
import { EmbedEventKeys } from '@revrag-ai/embed-react-native';
// Available event keys:
EmbedEventKeys.USER_DATA // 'user_data' - User identity and profile
EmbedEventKeys.SCREEN_STATE // 'state_data' - Application state and context
Event Usage Rules
CRITICAL REQUIREMENTS:
- USER_DATA event MUST be sent first before any other events
- USER_DATA must include
app_user_id
for user identification
- EmbedButton should only be rendered AFTER USER_DATA event is sent
- SCREEN_STATE events can only be sent after USER_DATA is established
Event Methods
import { Embed, EmbedEventKeys } from '@revrag-ai/embed-react-native';
// Send events
await Embed.Event(eventKey, data); //eventKey == EmbedEventKeys.USER_DATA || EmbedEventKeys.SATE_DATA
// Listen to events (optional)
Embed.on(eventKey, callback); //eventKey == EmbedEventKeys.USER_DATA || EmbedEventKeys.SATE_DATA
Event Flow Example
// Example event flow
try {
// Step 1: Send user data first (required)
await Embed.Event(EmbedEventKeys.USER_DATA, {
app_user_id: 'user123',
name: 'John Doe',
email: 'john@example.com',
});
// Step 2: Send context data (app_user_id auto-added)
await Embed.Event(EmbedEventKeys.SCREEN_STATE, {
screen: 'profile',
data: { plan: 'premium' },
});
} catch (error) {
console.error('Event error:', error);
}
Usage Examples
Complete Integration Example
import React, { useEffect, useState } from 'react';
import { View, StyleSheet, Alert } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import {
useInitialize,
EmbedButton,
Embed,
EmbedEventKeys
} from '@revrag-ai/embed-react-native';
export default function App() {
const [userDataSent, setUserDataSent] = useState(false);
const { isInitialized, error } = useInitialize({
apiKey: 'your_api_key_here',
embedUrl: 'https://your-embed-server.com',
});
// Initialize user data when SDK is ready
useEffect(() => {
if (isInitialized && !userDataSent) {
initializeUserData();
}
}, [isInitialized, userDataSent]);
const initializeUserData = async () => {
try {
// STEP 1: Send user data first (REQUIRED)
await Embed.Event(EmbedEventKeys.USER_DATA, {
app_user_id: 'user123', // Required field
name: 'John Doe',
email: 'john@example.com',
subscription: 'premium',
joinedDate: '2024-01-15',
});
setUserDataSent(true);
// STEP 2: Send initial screen state
await Embed.Event(EmbedEventKeys.SCREEN_STATE, {
screen: 'home',
timestamp: new Date().toISOString(),
userActions: [],
});
console.log('User data and initial state sent successfully');
} catch (error) {
console.error('Failed to initialize user data:', error);
Alert.alert('Error', 'Failed to initialize voice agent');
}
};
// Send screen state updates
const updateScreenState = async (screenName, data = {}) => {
if (!userDataSent) {
console.warn('Cannot send screen state before user data');
return;
}
try {
await Embed.Event(EmbedEventKeys.SCREEN_STATE, {
screen: screenName,
timestamp: new Date().toISOString(),
...data,
});
} catch (error) {
console.error('Failed to update screen state:', error);
}
};
// Handle initialization errors
if (error) {
console.error('SDK initialization failed:', error);
return (
<View style={styles.errorContainer}>
<Text>Failed to initialize voice agent</Text>
</View>
);
}
// Show loading while initializing
if (!isInitialized) {
return (
<View style={styles.loadingContainer}>
<Text>Initializing voice agent...</Text>
</View>
);
}
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.content}>
{/* Your app content */}
<YourAppComponents onScreenChange={updateScreenState} />
</View>
{/* Only render EmbedButton after user data is sent */}
{userDataSent && <EmbedButton />}
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
content: {
flex: 1,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Navigation Integration
import { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';
import { Embed, EmbedEventKeys } from '@revrag-ai/embed-react-native';
function NavigationListener() {
const navigation = useNavigation();
useEffect(() => {
const unsubscribe = navigation.addListener('state', (e) => {
const routeName = e.data.state.routes[e.data.state.index].name;
// Send screen state when navigation changes
Embed.Event(EmbedEventKeys.SCREEN_STATE, {
screen: routeName,
timestamp: new Date().toISOString(),
navigationStack: e.data.state.routes.map(route => route.name),
}).catch(console.error);
});
return unsubscribe;
}, [navigation]);
return null;
}
Troubleshooting
Common Issues
Best Practices
Event Optimization:
- Debounce frequent events to avoid overwhelming the API
- Batch related data in single events
- Handle offline scenarios with retry logic
- Store events locally when network is unavailable
Initialization Strategy:
- Show loading states during SDK initialization
- Handle initialization errors gracefully
- Send USER_DATA as early as possible in the app lifecycle
- Only render EmbedButton after successful initialization
Network & Security:
- Use HTTPS endpoints in production
- Test API connectivity during development
- Handle network failures gracefully
- Never bypass security requirements in production
Support
For additional help:
Last Updated: June 2025