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. At a high level:

  • You configure a VideoSDK.Builder with your credentials and an event observer.
  • VideoSDK.startVideoCall(...) returns a Fragment that you host inside your own layout container.
  • The observer delivers connection-state changes, errors, in-call button taps, and remote requests coming from the agent.
  • While the call is running you can drive it through VideoSDK (switch camera, toggle flash, end the call).

Steps at a glance:

  1. Acquire a profile token and prepare your credentials.
  2. Set up the event listener (observer).
  3. Configure the VideoSDK.Builder.
  4. Start the call and host the returned Fragment.
  5. Handle runtime controls and lifecycle events.
warning

The video call uses the device camera and microphone. Make sure the CAMERA and RECORD_AUDIO runtime permissions are granted before starting the call (see Preparation); otherwise the call cannot capture video or audio.

note

Helper methods such as replaceFragment(...) and removeFragment(...) used throughout the examples are your own app-side helpers for managing fragments — they are not part of the SDK.

Getting token

After completing the installation phase, you must initialize the SDK with a profile token acquired from the server, together with the server URLs and TURN credentials provided by Amani. You pass these values directly to the builder in Setting Video SDK Parameters.

Setting up the event listeners

Create a global AmaniVideoCallObserver object. It exposes four callbacks:

  • onConnectionState(...) — peer-connection state changes during the call.
  • onError(...) — any error that occurs during the call.
  • onUiEvent(...) — the SDK user tapped one of the in-call buttons.
  • onRemoteEvent(...) — the Studio agent requested an action remotely.

Add the imports below:

import ai.amani.videosdk.observer.AmaniVideoCallObserver
import ai.amani.videosdk.observer.ConnectionState
import ai.amani.videosdk.observer.AmaniVideoButtonEvents
import ai.amani.videosdk.observer.AmaniVideoRemoteEvents

Then create the observer object as shown below:

private val videoCallObserver: AmaniVideoCallObserver = object : AmaniVideoCallObserver{
override fun onConnectionState(connectionState: ConnectionState) {
when (connectionState) {
ConnectionState.CONNECTING -> {
//Agent is connecting to the call
}

ConnectionState.FAILED -> {
//Connection is failed
}

ConnectionState.CONNECTED -> {
//Agent is connected to the video call
}

ConnectionState.DISCONNECTED -> {
//Agent is disconnected from the call due to an unexpected situation such as
//power loss or possible internet connection issues
}

ConnectionState.BACKGROUNDED -> {
// Occurs when the app goes to the background, the screen is turned off, or an
//interruption like a phone call occurs. In this state, the fragment should be removed.
//Remove the fragment with your supported fragment manager from the stack
removeFragment(videoCallFragment)
}
}
}

override fun onError(error: String) {
//Any error during the call
}

override fun onUiEvent(
amaniVideoButtonEvents: AmaniVideoButtonEvents,
isActivated: Boolean
) {
when (amaniVideoButtonEvents) {
AmaniVideoButtonEvents.CALL_END -> {
//The call end button is tapped by the SDK user and the call is ended
}

AmaniVideoButtonEvents.CAMERA_SWITCH -> {
//The camera switch button is tapped by the SDK user and the camera is switched
}

AmaniVideoButtonEvents.MUTE -> {
//The mic mute button is tapped by the SDK user and the mic is muted
}

AmaniVideoButtonEvents.CAMERA_CLOSE -> {
//The camera close button is tapped by the SDK user and the camera is closed
}
}
}

override fun onRemoteEvent(
amaniVideoRemoteEvents: AmaniVideoRemoteEvents,
isActivated: Boolean
) {
when (amaniVideoRemoteEvents) {
AmaniVideoRemoteEvents.CALL_END -> {
//The call end button is tapped on the Studio agent side and the call is ended
}

AmaniVideoRemoteEvents.CAMERA_SWITCH -> {
//The camera switch is requested by the Studio agent. At this time
//you can ask the user to switch the camera, or switch it directly with
//VideoSDK.switchCamera() @see Extra Functions -> Camera Switch
}

AmaniVideoRemoteEvents.TORCH -> {
//The flash torch is requested by the Studio agent. At this time
//you can ask the user to enable the flash, or enable it directly with
//VideoSDK.toggleTorch() @see Extra Functions -> Toggle Flash
}
AmaniVideoRemoteEvents.CALL_ESCALATED -> {
//Triggered when the Studio requests the call to be transferred/forwarded to
//another agent. In this case you can restart the call as escalated by setting
//escalatedCall(true) on the builder. @see Setting Video SDK Parameters
}
}
}
}

Connection states (ConnectionState):

ValueMeaning
CONNECTINGConnection is being established.
CONNECTEDConnection is established and active.
DISCONNECTEDConnection was closed or terminated.
FAILEDConnection failed during setup or while active.
BACKGROUNDEDApp moved to the background; the connection keeps running but you should remove the call fragment.
warning

When you receive ConnectionState.BACKGROUNDED (app backgrounded, screen off, or an interruption such as an incoming phone call), remove the call Fragment from your fragment manager. Otherwise the call UI may stay in an inconsistent state.

Local UI button events (AmaniVideoButtonEvents) — triggered when the SDK user taps an in-call button: CAMERA_SWITCH, CAMERA_CLOSE, CALL_END, MUTE.

Remote events (AmaniVideoRemoteEvents) — requested by the Studio agent: CAMERA_SWITCH, CALL_END, TORCH, CALL_ESCALATED.

Setting Video SDK Parameters

Configure the VideoSDK.Builder you will use to start the call. Define it as a local val right where you start the call — you don't need to hold it as a global field.

Add the imports below:

import ai.amani.videosdk.VideoSDK

Then configure the builder as shown below:

val videoBuilder: VideoSDK.Builder = VideoSDK.Builder()
.nameSurname("Name Surname") //Mandatory field
.servers(
mainServerURL = "<socket server url>", //Mandatory field
stunServerURL = "<stun server url>", //Mandatory field
turnServerURL = "<turn server url>" //Mandatory field
)
.authentication(
token = "<profile token from the Acquire profile token API>", //Mandatory field
userName = "<turn server username>", //Mandatory field
password = "<turn server password>" //Mandatory field
)
.remoteViewAspectRatio(
VideoSDK.RemoteViewAspectRatio.Vertical //Default is Vertical, non mandatory field
)
.audioOptions(
VideoSDK.AudioOptions.SpeakerPhoneOn //Default is SpeakerPhoneOn, non mandatory field
)
.userInterface( //Has default user interface, non mandatory function
cameraSwitchButton = R.drawable.ic_camera_switch,
cameraSwitchButtonBackground = R.drawable.oval_gray,
microphoneMuteButton = R.drawable.ic_mic_on,
microphoneMuteButtonEnabled = R.drawable.ic_mic_off,
microphoneMuteButtonBackground = R.drawable.oval_gray,
cameraCloseButton = R.drawable.ic_camera_on,
cameraCloseButtonEnabled = R.drawable.ic_camera_off,
cameraCloseButtonBackground = R.drawable.oval_gray,
callEndButton = R.drawable.call_end,
callEndButtonBackground = R.drawable.oval_red
)
.videoCallObserver(videoCallObserver) //Mandatory field
.build() //Mandatory function

Each builder method is described below:

  • nameSurname(...) (required) — Customer's name and surname, formatted as "Name Surname".
  • servers(...) (required) — Server urls provided by Amani:
    • mainServerURL is the socket server url
    • stunServerURL is the stun server url
    • turnServerURL is the turn server url
  • authentication(...) (required):
    • token is the profile token generated by the Amani Api
    • userName is the turn server username
    • password is the turn server password
  • videoCallObserver(...) (required) — The observer defined in Setting up the event listeners.
  • remoteViewAspectRatio(...) (optional) — Aspect ratio of the remote view. Defaults to VideoSDK.RemoteViewAspectRatio.Vertical.
  • audioOptions(...) (optional) — Audio routing option. Defaults to VideoSDK.AudioOptions.SpeakerPhoneOn.
  • userInterface(...) (optional) — Overrides the default call UI drawables (camera switch, mute, camera close and call end buttons with their backgrounds).
  • escalatedCall(...) (optional) — Set to true to (re)start the call as an escalated call when the agent forwards it to another agent (see AmaniVideoRemoteEvents.CALL_ESCALATED). Defaults to false.
  • build() (required) — Builds the configured VideoSDK.Builder.

Start to use

VideoSDK.startVideoCall(...) returns a Fragment. This may be null, so null-check it before using it. Host the returned fragment in your own container (for example a FrameLayout in your layout), using the VideoSDK.Builder you configured in Setting Video SDK Parameters.

Add the imports below:

import ai.amani.videosdk.VideoSDK
import androidx.fragment.app.Fragment

Then start the video call and get its Fragment as shown below:

     val callFragment: Fragment? = VideoSDK.startVideoCall(videoBuilder)
callFragment?.let {
replaceFragment(R.id.container, callFragment)
}

Runtime Call Controls

These functions let you drive the call at runtime in response to remote requests from the Studio agent. They are exposed separately so you can ask the user for permission before acting on an agent's request — for example when you receive AmaniVideoRemoteEvents.CAMERA_SWITCH or AmaniVideoRemoteEvents.TORCH in onRemoteEvent. If the user agrees, call the matching function below.

Camera Switch

Call this in response to AmaniVideoRemoteEvents.CAMERA_SWITCH.

Add the imports below:

import ai.amani.videosdk.VideoSDK
import ai.amani.videosdk.observer.SwitchCameraObserver
import ai.amani.videosdk.observer.CameraPosition

Then switch the camera as shown below:

VideoSDK.switchCamera(object : SwitchCameraObserver {
override fun onSuccess(cameraPosition: CameraPosition) {
//The camera is switched successfully
}

override fun onException(exception: Throwable) {
//Exception happened during the camera switch
}
})

Toggle Flash

Call this in response to AmaniVideoRemoteEvents.TORCH.

Add the imports below:

import ai.amani.videosdk.VideoSDK
import ai.amani.videosdk.observer.ToggleTorchObserver

Then toggle the flash torch as shown below:

VideoSDK.toggleTorch(object : ToggleTorchObserver {
override fun onSuccess(isEnabled: Boolean) {
//The camera flash is enabled successfully
//Note: If the current camera is the front camera the flash will not be opened
}

override fun onError(error: Throwable) {
//Exception happened while toggling the flash torch
}
})

End Call

The endCall() function ends the ongoing video call and releases the current call fragment. Use it when you need to terminate the call programmatically from your own UI, instead of waiting for a call-end event from the SDK or the agent.

Add the imports below:

import ai.amani.videosdk.VideoSDK

Then end the call as shown below:

VideoSDK.endCall()