Embed Flutter SDK
A powerful Flutter SDK that provides a powerful voice-enabled AI-agent functionality with real-time widget tree monitoring for screen context fetching and realtime voice communication.Table of Contents
Installation
Add the following dependency to yourpubspec.yaml:
Android Configuration
Add the following permissions to yourandroid/app/src/main/AndroidManifest.xml:
iOS Configuration
Add the following permissions to yourios/Runner/Info.plist:
Getting Started
Initialization
Before using anyEmbedWidget, you must initialize the configuration once in your main.dart. You can initialize multiple API keys for different flows:
Note: Each embedInitialize() call saves the API key for that specific flow. When a user navigates to a route, the SDK automatically detects which flow the route belongs to and uses the corresponding API key.
Required: Navigator Observer
For route-based activation to work properly, you must addEmbedNavigatorObserver to your app’s navigator observers. This enables the SDK to track route changes and activate/deactivate the EmbedWidget accordingly.
For GoRouter:
Required: USER_DATA Event
To activate the EmbedWidget on the screen, you must call theUSER_DATA embedEvent with a user ID. This is typically done after user authentication or when you have a user identifier:
Important: The EmbedWidget will not be fully functional until the USER_DATA event is sent. This event initializes the voice communication features.
Optional: SCREEN_STATE Event
You can optionally sendSCREEN_STATE events to provide additional context about screen changes or user navigation:
Optional: CUSTOM_EVENT
CUSTOM_EVENT lets you capture bespoke analytics or interaction events that matter to your flows (for example, plan selections, or offer views). Supply any key/value metadata you want to track:
Available Events
| Event | Purpose | Required | When to Use |
|---|---|---|---|
USER_DATA | Initialize user context and activate EmbedWidget | Required | After user authentication or when user ID is available |
SCREEN_STATE | Provide screen context and navigation info | Optional | When navigating between screens or when screen context changes |
CUSTOM_EVENT | Capture bespoke user interactions | Optional | Whenever you need additional tracking for specific actions |
Basic Usage
Here’s a complete example showing how to use the SDK with flow-based activation:Required Parameters
child(required): The main content of your app
Flow-Based Activation
The SDK supports intelligent flow-based activation, allowing you to organize routes into flows and assign different API keys to each flow. When a user navigates to a route, the SDK automatically detects which flow the route belongs to and uses the corresponding API key.Basic Flow Configuration
How Flow-Based Activation Works
-
Flow Detection: When a user navigates to a route, the SDK automatically detects which flow the route belongs to based on your
enabledRoutesconfiguration. - API Key Selection: The SDK retrieves the API key that was saved for the detected flow during initialization.
-
Flow Switching: When switching between flows (or navigating outside any flow), the EmbedWidget automatically:
- Ends any active calls
- Re-initializes with the new flow’s API key when entering a new flow
-
Route Matching: Routes are matched using the
routeMatchModesetting (default:RouteMatchMode.exact).
Route Configuration Options
enabledRoutes:Map<String, List<String>>- Flow name to list of route names mapping- Key: Flow identifier (e.g.,
'flow 1','flow 2') - Value: List of route names that belong to that flow
- Key: Flow identifier (e.g.,
showOnAllRoutes: Show EmbedWidget on all routes (default:false)disabledRoutes: List of route names where EmbedWidget should be disabledrouteMatchMode: How to match routes:RouteMatchMode.exact- Exact match (default)RouteMatchMode.startsWith- Route starts with patternRouteMatchMode.contains- Route contains pattern
Optional Parameters
apiKey(optional): Your Revrag AI API key for authentication (can be set globally viaembedInitialize()withflowName)embedUrl(optional): Custom base URL for API endpoints (can be set globally viaembedInitialize())showEmbedWidget(default:true): Controls whether the embedded widget is visibleenabledRoutes(optional):Map<String, List<String>>- Flow name to route names mapping for flow-based activationshowOnAllRoutes(default:false): Show EmbedWidget on all routesdisabledRoutes(optional): List of route names where EmbedWidget should be disabledrouteMatchMode(default:RouteMatchMode.exact): How to match routesrightPadding(optional):double- Right padding in pixels from the screen edge for the Embed Widget’s position. When provided along withbottomPadding, the Embed Widget will be positioned from the right and bottom edges instead of using the default position.bottomPadding(optional):double- Bottom padding in pixels from the screen edge for the Embed Widget’s position. When provided along withrightPadding, the Embed Widget will be positioned from the right and bottom edges instead of using the default position.onPermissionStatusChanged(optional): A callback function that receives a boolean indicating whether microphone permission is denied or permanently denied. If the microphone permission is not given, the initial permission request is prompted automatically when the call is started. If the user denies it, the result can be handled accordingly. Called when a call is initiated:true- Microphone permission was grantedfalse- Microphone permission was denied or permanently denied
Customizing Embed Widget’s Position
You can customize the initial position of the Embed Widget usingrightPadding and bottomPadding parameters. These parameters allow you to position the Embed Widget from the right and bottom edges of the screen:
Using onPermissionStatusChanged
TheonPermissionStatusChanged callback allows you to handle microphone permission status changes when a user attempts to start a voice call. This is useful for showing custom UI feedback or handling permission denial gracefully:
- The callback is triggered when a user attempts to start a call
- It’s called after the permission request dialog is shown (if needed)
- It’s called before the call connection is established
Examples
Basic Integration
Form with Monitoring
Flow-Based Configuration
Configure the EmbedWidget with flow-based activation to organize routes into flows and use different API keys:Flow Behavior
- Within a Flow: When navigating between routes in the same flow, the EmbedWidget remains active and uses the same API key.
- Between Flows: When switching from one flow to another, the EmbedWidget:
- Automatically ends any active calls
- Cleans up resources
- Re-initializes with the new flow’s API key
- Outside Flows: When navigating to routes not in any configured flow, the EmbedWidget is hidden and cleaned up.
Custom Router Integration
An Example to show Full integration with Custom Routers we can take example of GoRouter for declarative navigation:Configuration
Custom Base URL
You can set a custom base URL globally during initialization:Troubleshooting
Common Issues
-
Widget Not Visible
- Check
showEmbedWidgetparameter - Verify API key is valid
- Check network connectivity
- Check
-
Voice Call Issues / Microphone Permission Not Being Requested
- Ensure microphone permission is granted and not permanently denied.
- Check device audio settings
-
iOS: Verify that
NSMicrophoneUsageDescriptionis added toios/Runner/Info.plist -
iOS: Ensure the Podfile includes the permission handler configuration. Add the following to your
ios/Podfileif it’s missing:After adding this configuration, run:
-
Widget Tree Not Updating
- Check widget tree handler initialization
- Verify context is available
- Check for widget disposal issues
-
Flow-Based Activation Not Working
- Verify route names match exactly (case-sensitive)
- Check
EmbedNavigatorObserveris added to router observers - Ensure GoRouter is properly configured with named routes
- Verify
enabledRoutesmap contains correct flow names and route names - Ensure each flow has been initialized with
embedInitialize()andflowNameparameter - Check that API keys are saved correctly for each flow (check console logs)
- Verify the current route belongs to a configured flow
-
Button Click Detection Issues
- Ensure buttons have proper keys for identification
- Check if buttons are properly tracked in widget tree
- Verify hit testing permissions and context
- Test with different button types (ElevatedButton, TextButton, etc.)
-
EmbedWidget Not Appearing on Expected Screens
- Check
enabledRoutesconfiguration (flow-based map structure) - Check
disabledRoutesconfiguration - Verify route matching mode (
exactvsstartsWithvscontains) - Check if
showEmbedWidgetis set totrue - Verify the route belongs to a configured flow
- Check console logs for flow detection messages
- Check
-
Wrong API Key Being Used for a Flow
- Verify
embedInitialize()was called with the correctflowNamefor each flow - Check that API keys are saved correctly (check console logs for
LocalStorageHandler.saveAPIKey) - Ensure flow names in
enabledRoutesmatch theflowNameused inembedInitialize() - Check console logs for
EmbedConfigService.apiKeyto see which API key is being retrieved
- Verify
License
This project is licensed under the Non-Commercial License License - see the LICENSE file for details.Support
- Documentation: https://docs.revrag.ai/embed/integration/flutter
- Email Support: [email protected]
- GitHub Issues: https://github.com/RevRag-ai/embed-react-native/issues