Embed Flutter SDK
Follow this guide in order the first time you integrate. Native microphone setup is required on both Android and iOS — skipping it is the most common source of “the mic dialog never appears” and silent voice failures.Introduction
Theembed_flutter SDK adds a voice AI agent to your app: a floating action button (FAB) backed by LiveKit, navigation-aware visibility, and a user-context channel to your embed backend.
Package: embed_flutter · Version: 0.0.17 · Requires: Flutter ≥ 3.0.0 / Dart ≥ 3.0.0
What you get out of the box
- Realtime voice with the agent through the FAB
- Screen and app context for richer conversations (route tracking via
EmbedNavigatorObserver/EmbedRouteListener, optional explicitSCREEN_STATE) - Event tracking: host-driven analytics and custom payloads via
embedEvent, plus agent lifecycle signals (embedOnAgent) - Server-driven UI for the FAB via
widget_configfrom device registration - Advanced FAB behavior (route flows/groups, show delays + policies, insets, continuity rules): covered in EmbedWidget advanced — read it once you move past a simple
enabledRouteslist
1. Installation
Add the package to yourpubspec.yaml:
1.1 Android Setup
Openandroid/app/src/main/AndroidManifest.xml and add:
1.2 iOS Setup
Step 1 — Info.plist Add the microphone usage description to yourios/Runner/Info.plist:
ios/Podfile to enable microphone permission requests. Add the PERMISSION_MICROPHONE=1 macro inside your post_install block:
2. How the SDK Works (Mental Model)
Understanding these three concepts up front makes integration straightforward:
Order of operations every time:
3. Initialization
CallembedInitialize() before runApp().
4. Wrapping Your App with EmbedWidget
EmbedWidget must be the outermost widget — it wraps your MaterialApp / MaterialApp.router / CupertinoApp.
The agent button appears only on routes listed in
enabledRoutes. On all other routes (e.g. splash, login, settings) it is hidden automatically.Available Events
Basic Usage
Here’s a complete example showing how to use the SDK with flow-based activation:EmbedNavigatorObserver intercepts every push, pop, and replace and shows or hides the agent button based on whether the new route is in enabledRoutes.
5.2 MaterialApp with onGenerateRoute
When routes carry parameters you typically useonGenerateRoute. Everything else is identical.
5.3 GoRouter
GoRouter uses thename field of each GoRoute for matching. Pass the observer in GoRouter.observers.
GoRouter with nameExtractor (path-based matching)
If you prefer to match on URL paths instead of route names, supply a nameExtractor to the observer:
enabledRoutes as usual.
5.4 GoRouter with ShellRoute (Bottom Tab Navigator)
ShellRoute keeps a persistent shell (e.g. a bottom navigation bar) while swapping child routes. The challenge is that ShellRoute children run inside a nested navigator — the top-level observer does not fire for them.
Solution: Wrap each tab’s screen with EmbedRouteListener. This widget notifies the SDK of the current screen whenever the tab is displayed.
5.5 MaterialApp Bottom TabNavigator (BottomNavigationBar)
When usingBottomNavigationBar with a plain MaterialApp, push a new named route for each tab using Navigator.pushReplacementNamed so the route stack stays shallow and the observer fires on every tab switch.
Navigator.pushReplacementNamedfiresdidReplaceonEmbedNavigatorObserver, which updates the current route in the SDK.- The SDK checks the new route name against
enabledRoutesand shows or hides the agent button — no extra code needed.
6. Sending Events
6.1 USER_DATA (Required)
This is the only required event. Send it after you have a logged-in user ID. It activates voice features and associates all future analytics with that user.The SDK queues this event internally if the server config hasn’t loaded yet and flushes it automatically — you do not need to wait or retry.
6.2 SCREEN_STATE (Optional)
Sends additional context about the current screen to the agent. Useful when you want the agent to know which step of a multi-step form the user is on, or when multiple routes share one screen widget.initState or whenever meaningful context changes (e.g. a stepper advances).
6.3 CUSTOM_EVENT (Optional)
Captures any interaction you want to relay to the agent — button taps, option selections, modal opens, etc.6.4 ANALYTICS_DATA (Optional)
LikeCUSTOM_EVENT but requires a named event identifier. Use this for conversion events, funnel steps, or any event you need to categorise by a fixed name on the backend.
7. EmbedWidget Parameters Reference
For per-flow visibility props —
embedButtonDelayMs, groupDelays,
groupContinuity, and groupInsets — see EmbedWidget advanced.7.1 Route Match Modes
By default route names must match exactly. UserouteMatchMode to relax this:
Leading slashes are normalised —
'home' and '/home' are treated identically.8. Advanced: Widget Visibility and Positioning
This section covers the common cases — custom position, show-on-all, and the mic callback. For route flows/groups, per-flow show delays + policies, continuity, and per-flow insets, see the companion guide:EmbedWidget advanced — FAB visibility (flows, delays, continuity, insets)
Important for production UX. Read it once you move past a simple
enabledRoutes list and need the FAB to behave differently per flow or screen.Custom FAB Position
Override the default floating button position withrightPadding and bottomPadding:
Show on All Routes with Exclusions
When you want the agent everywhere except a handful of screens:Microphone Permission Callback
Handle the case where the user denies microphone access when starting a call:onPermissionStatusChanged called?
- After the user taps the agent button and the permission dialog is shown.
- Before the call connection is established.
true= permission granted, the call will proceed.false= permission denied or permanently denied.
9. Advanced: Listening to SDK Events
Subscribe to events emitted by the agent from anywhere in your app.Agent lifecycle events
SdkEventName constants:
10. Utility Functions
11. Complete End-to-End Example
This example covers everything: GoRouter with a bottom tab shell,EmbedRouteListener for tabs, USER_DATA after login, SCREEN_STATE for sub-screen context, and CUSTOM_EVENT / ANALYTICS_DATA for interactions.
12. Troubleshooting
Agent button not visible
Agent not showing on a specific tab (ShellRoute / BottomNavigationBar)
iOS microphone permission never requested
GoRouter routes not tracked
Clearing SDK data on logout
Related documentation
EmbedWidget advanced — FAB visibility
Route flows/groups, per-flow show delays and policies, continuity, and
per-flow insets. The companion guide for production-grade FAB behavior.
Support
- Docs: https://docs.revrag.ai
- Email: contact@revrag.ai
embed_flutter: 0.0.17