ringg_flutter 0.1.2 copy "ringg_flutter: ^0.1.2" to clipboard
ringg_flutter: ^0.1.2 copied to clipboard

Ringg AI widget for Flutter — drop-in widget and headless controller for voice/text AI agents.

ringg_flutter #

Embeddable chat + voice-call widget for Ringg AI agents — the Flutter implementation. Drop RinggWidget over your app for text chat, Meet-style voice calls, interactive components (forms, calendars, quick replies, Block Kit) and a post-call feedback screen — or drive the headless core yourself without the bundled UI.

Install #

dependencies:
  ringg_flutter: ^0.1.2

Then flutter pub get. Requires Dart ≥ 3.6 · Flutter ≥ 3.27.

Platform setup (required for voice) #

Voice calls need microphone + audio permissions.

iOS — ios/Runner/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>Voice calls use the microphone.</string>
<key>UIBackgroundModes</key>
<array><string>audio</string></array>

Android — android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

Integrate in 3 steps #

Create a transport, build a controller with your agent config, then mount the widget. Hold the transport + controller in a State so you can dispose them.

1 · Get your credentials #

From the Ringg dashboard you need: your agent id, a widget API key (xApiKey) or a bearer authorization token, and the environment URLs (backend + LiveKit) for your account.

2 · Wire up a controller + widget #

import 'package:flutter/material.dart';
import 'package:ringg_flutter/ringg_flutter.dart';

class RinggSupport extends StatefulWidget {
  const RinggSupport({super.key});

  @override
  State<RinggSupport> createState() => _RinggSupportState();
}

class _RinggSupportState extends State<RinggSupport> {
  late final LiveKitTransport _livekit;
  late final RinggWidgetController _controller;

  // Environment URLs for your account (from the Ringg dashboard).
  static const _urls = <EnvironmentMode, EnvironmentUrls>{
    EnvironmentMode.prod: EnvironmentUrls(
      backendUrl: 'https://<your-backend-host>/ca/api/v0',
      livekitUrl: 'wss://<your-livekit-host>',
    ),
  };

  @override
  void initState() {
    super.initState();
    _livekit = createLiveKitTransport();
    _controller = RinggWidgetController(
      const RinggWidgetConfig(
        agentId: '<your-agent-id>',
        xApiKey: '<your-widget-api-key>',
        mode: EnvironmentMode.prod,     // selects the URL set above
        title: 'Support',
        description: 'How can we help?',
        defaultTab: MediaType.text,     // or MediaType.voice
      ),
      ControllerPorts(
        transport: _livekit.transport,
        urlResolver: const StaticUrlResolver(_urls),
      ),
    );
  }

  @override
  void dispose() {
    _controller.destroy();
    _livekit.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => RinggWidget(
        controller: _controller,
        transport: _livekit, // powers the voice-call audio visualizer
      );
}

3 · Mount it over your app #

RinggWidget places its own floating trigger + panel, so give it the full screen on top of your content:

Stack(
  children: const [
    YourApp(),
    RinggSupport(),
  ],
)

Tap the trigger → the chat/voice panel opens. That's the whole integration.

Native platforms & the Origin header. Browsers attach an Origin header automatically; native HTTP does not. If your Ringg backend allow-lists widget keys by domain, the webcall request will fail without it. Pass an httpClient (from package:http) that stamps the origin your key accepts:

ControllerPorts(
  transport: _livekit.transport,
  urlResolver: const StaticUrlResolver(_urls),
  httpClient: _originClient('https://your-allowed-origin'),
);
// where _originClient wraps http.Client and sets request.headers['Origin'].
// A ready-made version ships in the example (example/lib/origin_client.dart).

Configuration #

RinggWidgetConfig — only agentId is required; everything else is optional:

Field Type Purpose
agentId String your Ringg agent (required)
xApiKey String? widget API key
authorization String? bearer token (alternative to xApiKey)
mode EnvironmentMode? dev / stage / prod — picks the URL set
title / description String? panel header text
defaultTab MediaType? open in text or voice
hideTabSelector bool? hide the text/voice switch
defaultExpanded bool? open the panel on load
bypassStartScreen bool? jump straight into a call
variables Map<String, Object>? values for {{placeholders}} in agent prompts
logoUrl / theme / widgetPosition / legalDisclaimer / buttons branding, placement & styling

Headless use (no UI) #

Skip RinggWidget and drive the core directly — every piece of state is a Store<T> with snapshot + subscribe:

final unsubscribe = controller.messages.subscribe(
  (snap) => debugPrint('${snap.messages.length} messages'),
);

await controller.startCall(MediaType.text);
await controller.sendMessage('Hello!');

// later:
unsubscribe();
controller.destroy();

Example app #

A full, runnable harness — real backend + LiveKit (credentials via --dart-define), with a live config panel to try themes, tabs and interactive components — ships in the Example tab (the example/ directory), with its own README.md covering how to run it.

Platform support #

Android · iOS · macOS · Windows · Linux. Web is not supported.

Known issue — iOS 26.x simulators have no call audio #

On iOS 26.x simulator runtimes the audio engine has neither a working input (mic) nor output (playout) device — calls connect and transcripts stream, but you will not hear the agent or be able to unmute. This is an Apple simulator defect + upstream LiveKit limitation, not fixable app-side: client-sdk-swift#795, #849, Apple forums 738346, 803364. The widget degrades gracefully (listen-only attempt, no error). Test voice on a real device, an Android emulator, or macOS.

0
likes
0
points
113
downloads

Publisher

verified publisherringg.ai

Weekly Downloads

Ringg AI widget for Flutter — drop-in widget and headless controller for voice/text AI agents.

Homepage

License

unknown (license)

Dependencies

audioplayers, flutter, flutter_markdown_plus, flutter_svg, http, livekit_client, markdown, url_launcher

More

Packages that depend on ringg_flutter