The Telnyx Video Android SDK is simple to use and makes it easy to get started with video calling. With this SDK, you can easily add video calling to your app with just a few lines of code.
It provides all the functionality you need to join and interact with a Telnyx Room from an Android application.
A link to the repo can be found here:
Android SDK
Project structure
- SDK project: sdk module, containing all Telnyx SDK components as well as tests.
- Demo application: app module, containing a sample demo application utilizing the sdk module.
Adding the SDK to your Android client application
Add Jitpack.io as a repository within your root level build file:
Add the dependency within the app level build file:
Tag should be replaced with the release version.
Then, import the TelnyxVideo SDK into your application code at the top of the class:
The ’*’ symbol will import the whole SDK which will then be available for use within that class.
Remember to add and handle INTERNET, RECORD_AUDIO and ACCESS_NETWORK_STATE permissions in order to properly use the SDK.
Before connecting to a Room
Get an API Key
You’ll need an API key which is associated with your Mission Control Portal account under API Keys. You can learn how to do that here.
An API key is your credential to access our API. It allows you to:
- to authenicate to the Rest API
- to manage your access tokens
Create a Room to join (if it doesn’t exist)
In order to join a room you must create it, if it doesn’t already exist. See our Room Rest API to create one.
There’s also additional resources on other endpoints available to perform basic operations on a Room.
Generate an a client token to join a room
In order to join a room you must have a client token for that Room. The client token is short lived and you will be able to refresh it using the refresh token provided with it when you request a client token.
Please see the docs here to learn how to create a client token.
Now you are ready to connect to a video room that you previously created using the REST API.
Connect to Room
To connect, you’ll need to provide a participantName that will identify your user in that room.
You’ll also need to provide an instance of ExternalData that will contain a username of type String and an Integer id. You will also provide your Android application’s context in context
Publish video/audio stream
To publish as video or audio stream, we will need an instance of PublishConfigHelper with the application context, camera direction, streamKey (unique for each stream published), and streamId (unique for each stream published)
New streams can be created via the PublishConfigHelper class for both audio and video. They can be created together or added later independently.
Since stream is already created, it is only necessary to add the video track to PublishConfigHelper, and “update” the stream.
Remove video/audio track
To remove a video or audio track, publishConfigHelper has to be modified in order to remove the unwanted track
Remove stream
By removing the stream, we will remove all tracks added to it.
Video/Audio Observables
The Telnyx Video SDK for android works with mutable live data, and all the information you need to build your UI is provided through observables that will contain the most up to date information of the state of the room, such as current participant list, talking events, stream information, participants added, participants leaving, etc
State Observable
This observable will provide the current state of a room at any given moment.
We will receive a State object that will contain:
action -> “val action: String`
is the cause of the latest change of State
status -> val status: String
is the status of the Room session, when that action happened
participants -> val participants: List<Participant>
is the list of participants present in a room. A Participant is a UI representation in variables, for an attendee to the room session.
streams -> val streams: HashMap<Long, Stream>
this hash map, contains a track of the currently available streams and the id of the publisher streaming them.
A stream, will contain tracks for video, audio or both.
publishers -> val publishers: List<Publisher>
This will track all publishers in the room. A Publisher is an instance of an attendee or participant sharing some stream content in the room.
A single Participant, sharing multiple streams can be also linked to multiple Publisher ids.
subscriptions -> val subscriptions: List<Subscription>
Each time a publisher starts streaming information, we will have the option of subscribe/unsubscribe to/from it. This list will track all the subscriptions.
Event observables
Some observables will have a MutableLiveData of Event. Event is a wrapper of LiveData, and provide the means to ensure we only handle an observable once, no matter how many times we’re set to observe it.
If the contents have already been handled, we won’t get that content again, unless we peekContent() instead.
Participants Observable
This mutable list will be received as soon as we join a Room session, and contains a list of the participants already present in the room, including yourself. The SDK will keep this list updated but won’t post the changes, so this observer won’t be fired again. See Participant
By receiving this list we can initialize a recycler adapter in order to show participants:
Joined Room Observable
This mutable will fire an event as soon as we have connected to a room, and we have retrieved an initial list of Participants
It is useful when we want to update UI as soon as we have joined the room sucessfully.
This will be different to Status-CONNECTED that will be issued when we have successfully joined our plugins to handle session audio. See Status.
Joined Participant Observable
We receive the participant that has joined the room after client has already joined.
We can add the this reference to the list used in our adapter as:
Leaving participant id Observable
We receive the publisherId that has leaved the room, and a reason for its exit (“Left” or “Kicked”).
Connected to room Observable
Receive true when we have opened a webSocket and connected to the room
Participant stream changed Observable
We will receive here an event with the participant that has recently changed its video and/or audio stream status. Mutable list of participants will also be updated with this change, but here the specific individual is received.
Stream status
These status apply for audio, video and shared screen:
UNKNOWN : initial status. We don’t have information on whether this participant is sharing audio/video/screen
ENABLED : the participant is sharing audio/video/screen and we can subscribe to a stream for it like:
DISABLED : the participant is not sharing audio/video/screen. If we were subscribed to that participant audio/video/screen we can unsubscribe from it.
Subscribe to a video stream
In order to subscribe to a video stream, there are 3 actions that needs to be performed:
1 Provide the SDK with the same instance of SurfaceViewRenderer you want to init:
This will use the proper WebRTC Connection to provide an EglContext for the surface to be init
2 Use method addSink() to add a SurfaceViewRenderer instance to the videoTrack provided for a Participant, and set that track to enable videoTrack?.setEnabled(true)
3 Subscribe to the stream a participant is providing
participantId is the participant id that uniquely identifies a single participant in the room
streamKey i.e: “SharingSubscriptions” “CameraSubscriptions”
streamConfig whether we want to subscribe to audio/video or both. By default we will attempt both.
Remove subscription to a *video stream
To remove a subscription we need to issue
A good practice when handling surfaces is to make sure you remove this surface properly from the rendering context before eliminating or removing the surface from the UI:
Participant Talking Observable
We will receive the participant that has updated its talking status, and the stream key. This information is also modified in the Participants list
Stats
We provide the method getWebRTCStatsForStream() to retrieve WebRTC stats
This request brings stats one time only, so if you want to keep receiving stats, you will need to use some sort of runnable or coroutine to recursively request for them such as:
We have to provide participantId, streamKey that is the key that identifies the stream we need the stats from, and callback that is an RTCStatsCollectorCallback we provide to the WebRTC peer connection in order to retrieve the stats.
In Kotlin, method call will look like this
We can later parse the information retrieved to obtain the specific information we go after.
In our sample app, you will see the models we use for audio and video, both local and remote
Remote Video stats
WEBRTC’s RTCStatsReport can be parsed and mapped to RemoteVideoStreamStats
Local Video stats
WEBRTC’s RTCStatsReport can be parsed and mapped to LocalVideoStreamStats
Remote audio stats
WEBRTC’s RTCStatsReport can be parsed and mapped to RemoteAudioStreamStats
Local audio stats
WEBRTC’s RTCStatsReport can be parsed and mapped to LocalAudioStreamStats