Skip to main content

Initializing and using the SDK

Overview​

The Amani Video SDK connects your user to a Studio agent over a WebRTC video call. This package is a thin React Native bridge over the native iOS (AmaniVideoBuilder / AmaniVideo) and Android (VideoSDK.Builder) SDKs — it exposes one JS class, AmaniVideoCall, whose methods and events behave the same on both platforms wherever the underlying native SDKs agree, and are called out individually where they don't.

At a high level:

  • You create an AmaniVideoCall instance — one instance per call.
  • configure(...) builds the native call session from your credentials.
  • present(...) shows the native full-screen call UI and starts connecting.
  • addListener(...) delivers connection-state changes, errors, in-call button taps, and remote requests coming from the agent — all through a single callback.
  • While the call is running you drive it through the same instance (switch camera, toggle flash, close the call).

Steps at a glance:

  1. Acquire a profile token and prepare your credentials.
  2. Set up the event listener.
  3. Configure the call.
  4. Present the call.
  5. Handle runtime controls and lifecycle events.
warning

The video call uses the device camera and microphone. Make sure those permissions are granted before calling present() (see Preparation) — this bridge does not request them itself, and the call cannot capture video or audio without them.

Getting token​

After completing the installation phase, you must configure the call with a profile token acquired from your server, together with the server URLs and TURN credentials provided by Amani. You pass these values directly to configure(...) in Configuring the call.

Setting up the event listener​

Unlike the native iOS delegate (four separate methods) and Android observer (four separate callbacks), this bridge exposes one listener that receives every event as a discriminated union on its type field. Subscribe with addListener(...), which returns an unsubscribe function.

import { AmaniVideoCall } from 'amani-react-native-videosdk';
import type { AmaniVideoEvent } from 'amani-react-native-videosdk';

const call = new AmaniVideoCall();

const unsubscribe = call.addListener((event: AmaniVideoEvent) => {
switch (event.type) {
case 'connectionState':
// connecting | connected | disconnected | failed | backgrounded (Android only)
console.log('connection state:', event.state);
break;

case 'exception':
// any error that occurred during the call
console.warn('native error:', event.messages);
break;

case 'uiEvent':
// the local user tapped an in-call button: cameraSwitch | cameraClose | callEnd | mute | torch
break;

case 'remoteEvent':
// the Studio agent requested something remotely: cameraSwitch | callEnd | torch | escalated | capturePhotoRequested
if (event.event === 'cameraSwitch') call.switchCamera();
if (event.event === 'torch') call.toggleTorch();
break;

case 'devicePhotoCaptured':
// see "Device photo capture" below
// event.image is a ready-to-use data URI: <Image source={{ uri: event.image }} />
break;
}
});

// later, e.g. on unmount
unsubscribe();

Connection states (event.state on connectionState):

ValueMeaning
connectingConnection is being established.
connectedConnection is established and active.
disconnectedConnection was closed or terminated.
failedConnection failed during setup or while active.
backgroundedAndroid only. App moved to the background, screen turned off, or a call interrupted the app. undefined/never fires on iOS.

Local UI button events (event.event on uiEvent) — triggered when the SDK user taps an in-call button: cameraSwitch, cameraClose, callEnd, mute, torch.

Remote events (event.event on remoteEvent) — requested by the Studio agent: cameraSwitch, callEnd, torch, escalated, capturePhotoRequested (see Device photo capture below).

note

On uiEvent and remoteEvent, the isActivated: boolean field is Android only (e.g. it distinguishes mute-on from mute-off) — it's always undefined on iOS.

Configuring the call​

Call configure(...) with your credentials. It builds the native session but shows no UI yet.

await call.configure({
serverUrl: 'https://videocall.example',
token: customerToken, // fetched from the Amani API by your backend
name: 'John',
surname: 'Doe',
stunServerUrl: 'stun:example.stun.server:3478',
turnServerUrl: 'turn:example.turn.server:3478',
turnUsername: 'turn_user',
turnPassword: 'turn_password',
});

configure(...) accepts:

FieldRequiredNotes
serverUrl, token, name, surnameYes
stunServerUrl, turnServerUrl, turnUsername, turnPasswordYes
viewModeNo'portrait' (default) or 'landscape'
backgroundColorNoHex string, e.g. "#1A1A1A". Supported on both platforms.
buttonColorsNoHex colors per button (see below). iOS only.

buttonColors (iOS only)​

await call.configure({
// ...required fields
buttonColors: {
switchCameraButton: '#FFFFFF',
switchCameraButtonBackground: '#000000',
closeCameraButton: '#FFFFFF',
closeCameraButtonBackground: '#000000',
muteButton: '#FFFFFF',
muteButtonBackground: '#000000',
endCallButton: '#FFFFFF',
endCallButtonBackground: '#FF0000',
},
});

This is iOS only because Android's native builder takes drawable resource IDs for its buttons, not runtime colors — supporting it there would require shipping bundled drawables and doing runtime tinting, which isn't currently done.

Custom icon images (buttonIcons) aren't exposed on either platform.

Presenting the call​

present(...) shows the native full-screen call UI and starts connecting, using the session built by configure(...).

await call.present({ callStatus: 'waiting' }); // or 'escalated'

callStatus defaults to 'waiting'. Set it to 'escalated' when you're re-presenting the call in response to an escalated remote event (the Studio agent forwarding the call to another agent).

note

There's no embedded/inline view on either platform — present() always shows the call full-screen on top of your app's current activity/view controller.

Runtime Call Controls​

These functions let you drive the call at runtime, typically in response to a remoteEvent from the Studio agent — for example asking the user for permission before acting on cameraSwitch or torch.

Camera Switch​

Call this in response to a remoteEvent with event: 'cameraSwitch', or from your own UI.

await call.switchCamera();

Toggle Flash​

Call this in response to a remoteEvent with event: 'torch'. Only has an effect while the back camera is active.

await call.toggleTorch();

End Call​

Tears down the call and dismisses the native UI. Safe to call even if the call was never presented.

await call.close();

Device photo capture (agent-triggered)​

During a call the Studio agent can trigger a device-camera capture — a burst of 4 full-resolution photos taken with the phone's own camera (not a screenshot of the video stream), so image quality isn't affected by the call's video bitrate. This can't be triggered from the customer side; it's entirely agent-initiated.

You'll see two events through addListener(...):

  1. A remoteEvent with event: 'capturePhotoRequested' fires immediately when the agent starts a capture — useful for showing your own "capturing…" UI (the native SDK also shows its own brief flash animation).
  2. A devicePhotoCaptured event fires once per photo (total is currently always 4) as each one is taken.

The photos are sent to the agent automatically regardless of whether you handle these events — listening to them is only needed if you also want the images or the "capture started" moment available in your own app.

case 'remoteEvent':
if (event.event === 'capturePhotoRequested') {
// show your own "capturing…" UI
}
break;
case 'devicePhotoCaptured':
console.log(`photo ${event.index + 1}/${event.total} for burst ${event.captureId}`);
// event.image is a data URI: <Image source={{ uri: event.image }} />
break;

Requires AmaniVideoSDK >= 2.2.0 (this bridge's podspec already pins that).