At a glance
| Platform | Package | Install | Requires |
|---|---|---|---|
| Flutter | gravix_rtc on pub.dev | flutter pub add gravix_rtc | Flutter 3.38+, Dart 3.10+ |
| Web | gravix-rtc on npm | npm install gravix-rtc | A browser with WebRTC, page served over HTTPS |
| Android | gravix_rtc (Flutter) | As Flutter | Android 7.0 (API 24)+ |
| iOS | gravix_rtc (Flutter) | As Flutter | iOS 13+ |
Before you start
Every SDK joins a room with an access token that your server signs with your App ID and App Certificate. The App Certificate never goes into an app. If you have not built that endpoint yet, start with access tokens: it is about twenty lines of Node or Go.
In the examples below, https://YOUR-BACKEND/rtc/token is that endpoint. It answers with { token, url }, where url is your region URL from the dashboard (wss://YOUR-REGION-URL).
Flutter
gravix_rtc is one package with one import. GravixRoomService runs the room: connect and leave, mic and camera, active speakers and reconnects, with state exposed as ValueNotifiers.
Install
flutter pub add gravix_rtcPlatform setup
Declare microphone and camera access for each platform you ship. Ask for the permissions at runtime before the user joins with mic or camera on.
<!-- android/app/src/main/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- Bluetooth headsets: Android 12+ needs BLUETOOTH_CONNECT -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<!-- ... your <application> ... -->
</manifest><!-- ios/Runner/Info.plist -->
<key>NSMicrophoneUsageDescription</key>
<string>Talk in calls</string>
<key>NSCameraUsageDescription</key>
<string>Video in calls</string>
<!-- Keep call audio playing with the screen locked or the app in the background -->
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>Join a room
import 'package:gravix_rtc/gravix_rtc.dart';
// One provider per signed-in user. It caches each token until it is about to expire.
final tokens = GravixTokenProvider.endpoint(
Uri.parse('https://YOUR-BACKEND/rtc/token'),
headers: {'Authorization': 'Bearer $sessionJwt'}, // your app's own login session
);
final room = GravixRoomService();
Future<void> join(String roomId, String userId, String name) async {
room.onRemoteVideoTrack = (uid, track) {
// show it with VideoTrackRenderer(track)
};
final ok = await room.connectWithTokenProvider(
tokenProvider: tokens,
request: GravixTokenRequest(
room: roomId,
identity: userId,
name: name,
canPublish: true,
),
publishMic: true,
enableVideo: true,
);
if (!ok) {
// room.lastTokenError is set when your token endpoint failed
}
}
Future<void> leave() => room.disconnect();canPublishin the request is what the app asks for. Your server decides what goes into the token.- Build one token provider per signed-in user and keep it: tokens are cached until shortly before they expire, so a join does not wait for your server twice.
room.activeSpeakerstells you who is talking, for a speaking ring or a seat glow.
Web
gravix-rtc is the browser SDK, written in TypeScript. The browser asks the user for microphone and camera access the first time you turn them on, and only on pages served over HTTPS (a local development server on your own machine also works).
Install
npm install gravix-rtcJoin a room
import { Room, RoomEvent, GravixTokenProvider, connectWithTokenProvider } from 'gravix-rtc';
// Calls YOUR backend with the user's session cookie. Tokens are cached until they expire.
const tokens = GravixTokenProvider.endpoint('https://YOUR-BACKEND/rtc/token', {
credentials: 'include',
});
const room = new Room();
const stage = document.getElementById('stage')!;
room
.on(RoomEvent.TrackSubscribed, (track) => {
stage.appendChild(track.attach()); // a <video> or <audio> element
})
.on(RoomEvent.TrackUnsubscribed, (track) => {
track.detach().forEach((el) => el.remove());
});
export async function join(roomId: string, userId: string, name: string) {
await connectWithTokenProvider(room, {
tokenProvider: tokens,
request: { room: roomId, identity: userId, name },
});
await room.localParticipant.setMicrophoneEnabled(true);
await room.localParticipant.setCameraEnabled(true);
}
export const leave = () => room.disconnect();credentials: 'include'sends your app's session cookie, so your endpoint knows who is asking. You can passheadersinstead.track.attach()returns a ready<video>or<audio>element for each remote track.- Turn the camera off with
room.localParticipant.setCameraEnabled(false), and the microphone the same way.
Android
Build Android apps with the Flutter SDK, gravix_rtc: follow the Flutter steps. A separate native Android (Kotlin) SDK is not available today. If you need one, tell us.
- Minimum Android 7.0 (API 24).
- Permissions:
RECORD_AUDIOandCAMERA, requested at runtime;BLUETOOTH_CONNECTon Android 12+ so Bluetooth headsets are found. - Background: on Android 11 and later an app that is not on screen loses its microphone a few seconds after the user leaves it. The SDK ships a foreground service for calls. It is off by default; turn it on once before the first join.
// Android: keep the microphone alive when the user leaves the app (off by default).
// Turn it on once, before the first join.
GravixForegroundService.defaults = const GravixForegroundServiceOptions(
enabled: true,
notificationTitle: 'Live room',
notificationText: 'Tap to return',
showLeaveAction: true,
);
GravixForegroundService.leaveRequests.listen((_) => leave());The service needs RECORD_AUDIO granted before the user takes a seat. If your app already runs its own call service, keep this one off so users do not see two call notifications.
iOS
Build iOS apps with the Flutter SDK, gravix_rtc: follow the Flutter steps. A separate native iOS (Swift) SDK is not available today. If you need one, tell us.
- Minimum iOS 13.
NSMicrophoneUsageDescriptionandNSCameraUsageDescriptioninInfo.plist(see platform setup).- Add the
audiobackground mode to keep a call audible with the screen locked. - The SDK manages the audio session: speaker, earpiece and Bluetooth routing work without extra code.
