Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Getting Started with Android v5.x


(warning)

Warning

This documentation is for reference only. We are no longer onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2026(link takes you to an external page).

We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide(link takes you to an external page) to assist you in minimizing any service disruption.

To make sure your app is ready for Android 11 please visit this page(link takes you to an external page).


Contents

contents page anchor

This guide provides you with an overview of the key objects you'll use in the Programmable Video API to build your video application with the Twilio Programmable Video Android SDK.

Note: If you haven't already done so, take a look at the open source video collaboration app(link takes you to an external page) and quickstart apps(link takes you to an external page). Then come back to this guide for more detail on how to add video to your own app.

If you've worked with WebRTC in the past, you'll find that Programmable Video provides a simple wrapper around WebRTC's lower-level APIs to make it easy to build rich audio and video applications. You can still access lower-level primitives, but that's not required to get started.

Additionally, Programmable Video provides the missing pieces required to use WebRTC to build sophisticated applications: Global STUN/TURN relays, media services for large-scale group conferences and recording, and signaling infrastructure are all included.


Let's start with an overview of the Programmable Video API:

  • A Room represents a real-time audio, video, and/or screen-share session, and is the basic building block for a Programmable Video application.
  • In a Peer-to-peer Room , media flows directly between participants. Supports up to 10 participants in a mesh topology.
  • In a Group Room , media is routed through Twilio's Media Servers. Supports up to 50 participants.
  • Participants represent client applications that are connected to a Room and sharing audio and/or video media with one another.
  • Tracks represent the individual audio and video media streams that are shared within a Room.
  • LocalTracks represent the audio and video captured from the local microphone and camera.
  • RemoteTracks represent the audio and video tracks from other participants connected to the Room.

The following code samples illustrate common tasks that you as a developer may wish to perform related to a Room and its Participants.


To start using the Android Programmable Video SDK in your apps, you need to perform a few basic tasks first.


1. Get the Programmable Video Android SDK

1-get-the-programmable-video-android-sdk page anchor

The Android Video SDK is distributed through Maven Central.

To install the Android Video SDK, ensure the following configuration is in your build.gradle file:

Maven Central.

Gradle

gradle page anchor

Note: Versions prior to 6.3.0 depend on a version of ReLinker that is only hosted on JCenter. Thus, if you are using one of these SDK versions, then the ReLinker dependency will need to be manually added to your application's build.gradle dependencies block. See the ReLinker Github readme(link takes you to an external page) to learn how to properly setup the dependency.


_15
allprojects {
_15
repositories {
_15
mavenCentral()
_15
}
_15
}
_15
_15
// The Video library resides on Maven Central
_15
implementation 'com.twilio:video-android:$version'
_15
_15
android {
_15
compileOptions {
_15
sourceCompatibility 1.8
_15
targetCompatibility 1.8
_15
}
_15
}

Add the following lines to your proguard-project.txt file.


_10
-keep class tvi.webrtc.** { *; }
_10
-keep class com.twilio.video.** { *; }
_10
-keepattributes InnerClasses

The Android SDK supports Android API level 16 and higher. It is built for armeabi-v7a, arm64-v8a, x86, and x86_64 architectures.

API Keys represent credentials to access the Twilio API. They are used for two purposes:

For the purposes of this guide, we will create our API Key from the Twilio Console.

3. Generate an Access Token

3-generate-an-access-token page anchor

To execute the code samples below, you'll need to generate an Access Token. An Access Token is a short-lived credential used to authenticate your client-side application to Twilio.

In a production application, your back-end server will need to generate an Access Token for every user in your application. An Access Token is a short-lived credential used to authenticate your client-side application to Twilio. Visit the User Identity and Access Token guide to learn more.


Call Video.connect() to connect to a Room from your Android application. Once connected, you can send and receive audio and video streams with other Participants who are connected to the Room.


_18
private Room.Listener roomListener() {
_18
return new Room.Listener() {
_18
@Override
_18
public void onConnected(Room room) {
_18
Log.d(TAG,"Connected to " + room.getName());
_18
}
_18
}
_18
}
_18
_18
public void connectToRoom(String roomName) {
_18
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
_18
.roomName(roomName)
_18
.audioTracks(localAudioTracks)
_18
.videoTracks(localVideoTracks)
_18
.dataTracks(localDataTracks)
_18
.build();
_18
room = Video.connect(context, connectOptions, roomListener);
_18
}

You must pass the Access Token when connecting to a Room. You may also optionally pass the following:

  • A room name , which allows you to dynamically specify the name of the Room you wish to join. (Note: You can also encode the Room name in the Access Token, which will allow the user to connect to only the Room specified in the token.)
  • Local audio, video, or data tracks , to begin sharing pre-created local media with other Participants in the Room upon connecting.

The name of the Room specifies which Room you wish to join. If a Room by that name does not already exist, it will be created upon connection. If a Room by that name is already active, you'll be connected to the Room and receive notifications from any other Participants also connected to the same Room. Room names must be unique within an account.

You can also create a Room using the Rooms REST API. Look at the REST API Rooms resource docs for more details.

Example: Create a Room called DailyStandup


_10
curl -XPOST 'https://video.twilio.com/v1/Rooms' \
_10
-u '{API Key SID}:{API Secret}' \
_10
-d 'UniqueName=DailyStandup'

Note: If you don't specify a Type attribute, then Twilio will create a Group Room by default.


You can also set the room type from the Room Settings(link takes you to an external page) page in the Twilio Video Console. Twilio will use the room type set on Room Settings page, when you create a room from the client-side or the REST API.

Note: Twilio will set the Room Type as Group by default on the Room Settings page.

Once a Room is created, Twilio will fire a room-created webhook event, if the StatusCallback URL is set. You can set the StatusCallback URL on the Room Settings(link takes you to an external page) page, if you want create a room from the client-side. If you create a room using the REST API, then you need to provide a StatusCallback URL while creating the room.


_10
curl -XPOST 'https://video.twilio.com/v1/Rooms' \
_10
-u '{API Key SID}:{API Secret}' \
_10
-d 'UniqueName=DailyStandup' \
_10
-d 'StatusCallback=https://hooks.yoursite.com/room-events' \
_10
-d 'StatusCallbackMethod=POST' \
_10
-d 'Type=group'


Enabling Room Recordings

enabling-room-recordings page anchor

Recordings can be enabled only on Group Rooms. Set Recordings to Enabled to record participants when they connect to a Group Room. Recordings can also be enabled on Group Rooms through via the Rest API at Room creation time by setting the RecordParticipantsOnConnect property to true.


_10
curl -XPOST 'https://video.twilio.com/v1/Rooms' \
_10
-u 'SKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_api_key_secret' \
_10
-d 'UniqueName=DailyStandup' \
_10
-d 'Type=group' \
_10
-d 'RecordParticipantsOnConnect=true' \
_10
-d 'StatusCallback=http://example.org'


If you'd like to join a Room you know already exists, you handle that exactly the same way as creating a room: just pass the Room name to the connect method. Once in a Room, you'll receive a participantConnectedevent for each Participant that successfully joins. Querying the participants getter will return any existing Participants who have already joined the Room.


_18
private Room.Listener roomListener() {
_18
return new Room.Listener() {
_18
@Override
_18
public void onConnected(Room room) {
_18
Log.d(TAG,"Connected to " + room.getName());
_18
}
_18
}
_18
}
_18
_18
public void connectToRoom(String roomName) {
_18
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
_18
.roomName(roomName)
_18
.audioTracks(localAudioTracks)
_18
.videoTracks(localVideoTracks)
_18
.dataTracks(localDataTracks)
_18
.build();
_18
room = Video.connect(context, connectOptions, roomListener);
_18
}


You can capture local media from your device's microphone, camera or screen-share on different platforms in the following ways:

In an Android application, begin capturing audio data by creating a LocalAudioTrack, and begin capturing video by adding a LocalVideoTrack with an associated VideoCapturer. The Android Video SDK provides customizable video capturers for both camera and screen capture.


_23
// Create an audio track
_23
boolean enable = true;
_23
LocalAudioTrack localAudioTrack = LocalAudioTrack.create(context, enable);
_23
_23
// A video track requires an implementation of VideoCapturer
_23
CameraCapturer cameraCapturer = new CameraCapturer(context,
_23
CameraCapturer.CameraSource.FRONT_CAMERA);
_23
_23
// Create a video track
_23
LocalVideoTrack localVideoTrack = LocalVideoTrack.create(context, enable, cameraCapturer);
_23
_23
// Rendering a local video track requires an implementation of VideoRenderer
_23
// Let's assume we have added a VideoView in our view hierarchy
_23
VideoView videoView = (VideoView) findViewById(R.id.video_view);
_23
_23
// Render a local video track to preview your camera
_23
localVideoTrack.addRenderer(videoView);
_23
_23
// Release the audio track to free native memory resources
_23
localAudioTrack.release();
_23
_23
// Release the video track to free native memory resources
_23
localVideoTrack.release();


Connect as a publish-only Participant

connect-as-a-publish-only-participant page anchor

For some use cases you may wish to connect as a publish-only Participant that is not subscribed to any Tracks. If you are connecting to a Group Room, you may disable automatic subscription behavior via ConnectOptions.


_10
public void connectToRoom(String roomName) {
_10
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
_10
.roomName("my-room")
_10
.enableAutomaticSubscription(false)
_10
.build();
_10
room = Video.connect(context, connectOptions, roomListener);
_10
}


Working with Remote Participants

working-with-remote-participants page anchor

Handle Connected Participants

handle-connected-participants page anchor

When you join a Room, Participants may already be present. You can check for existing Participants in the connected event callback by using the participantsgetter.


_37
// Connect to room
_37
Room room = Video.connect(context, connectOptions, new Room.Listener() {
_37
@Override
_37
public void onConnected(Room room) {}
_37
_37
@Override
_37
public void onConnectFailure(Room room, TwilioException e) {}
_37
_37
@Override
_37
public void onDisconnected(Room room, TwilioException e) {}
_37
_37
@Override
_37
public void onRecordingStarted(Room room) {}
_37
_37
@Override
_37
public void onRecordingStopped(Room room) {}
_37
_37
@Override
_37
public void onParticipantConnected(Room room, RemoteParticipant participant) {
_37
Log.i("Room.Listener", participant.getIdentity() + " has joined the room.");
_37
}
_37
_37
@Override
_37
public void onParticipantDisconnected(Room room, RemoteParticipant participant) {
_37
Log.i("Room.Listener", participant.getIdentity() + " has left the room.");
_37
}
_37
);
_37
_37
// ... Assume we have received the connected callback
_37
_37
// After receiving the connected callback the LocalParticipant becomes available
_37
LocalParticipant localParticipant = room.getLocalParticipant();
_37
Log.i("LocalParticipant ", localParticipant.getIdentity());
_37
_37
// Get the first participant from the room
_37
RemoteParticipant participant = room.getRemoteParticipants().get(0);
_37
Log.i("HandleParticipants", participant.getIdentity() + " is in the room.");

Handle Participant Connection Events

handle-participant-connection-events page anchor

When Participants connect to or disconnect from a Room that you're connected to, you'll be notified via an event listener: Similar to Room Events, Twilio will fire Participant events if the StatusCallback webhook URL is set when the Room is created. These events help your application keep track of the participants who join or leave a Room.


_14
private Room.Listener roomListener() {
_14
return new Room.Listener() {
_14
_14
@Override
_14
public void onParticipantConnected(Room room, RemoteParticipant participant) {
_14
Log.v(TAG, "Participant connected: " + participant.getIdentity());
_14
}
_14
_14
@Override
_14
public void onParticipantDisconnected(Room room, RemoteParticipant participant) {
_14
Log.v(TAG, "Participant disconnected: " + participant.getIdentity());
_14
}
_14
};
_14
}

Display a Remote Participant's Video

display-a-remote-participants-video page anchor

To see the Video Tracks being sent by remote Participants, we need to render them to the screen:


_23
// First, we set a Media Listener when a Participant first connects:
_23
private Room.Listener roomListener() {
_23
return new Room.Listener() {
_23
@Override
_23
public void onParticipantConnected(Room room, RemoteParticipant participant) {
_23
participant.setListener(remoteParticipantListener());
_23
}
_23
};
_23
}
_23
_23
/* In the Participant listener, we can respond when the Participant adds a Video
_23
Track by rendering it on screen: */
_23
private RemoteParticipant.Listener remoteParticipantListener() {
_23
return new RemoteParticipant.Listener() {
_23
@Override
_23
public void onVideoTrackSubscribed(RemoteParticipant participant,
_23
RemoteVideoTrackPublication remoteVideoTrackPublication,
_23
RemoteVideoTrack remoteVideoTrack) {
_23
primaryVideoView.setMirror(false);
_23
remoteVideoTrack.addRenderer(primaryVideoView);
_23
}
_23
};
_23
}


Display a Camera Preview

display-a-camera-preview page anchor

Sometimes you need to make sure you're looking fantastic before entering a Room. We get it. Each SDK provides a means to render a local camera preview outside the context of an active Room:


_16
/* The CameraCapturer is a default video capturer provided by Twilio which can
_16
capture video from the front or rear-facing device camera */
_16
private CameraCapturer cameraCapturer;
_16
_16
/* A VideoView receives frames from a local or remote video track and renders them
_16
to an associated view. */
_16
private VideoView primaryVideoView;
_16
_16
// Initialize the camera capturer and start the camera preview
_16
cameraCapturer = new CameraCapturer(this, CameraSource.FRONT_CAMERA);
_16
LocalVideoTrack localVideoTrack = LocalVideoTrack.create(context, true, cameraCapturer);
_16
primaryVideoView.setMirror(true);
_16
localVideoTrack.addRenderer(primaryVideoView);
_16
_16
// Release the local video track to free native memory resources once you are done
_16
localVideoTrack.release();

You can disconnect from a Room you're currently participating in. Other Participants will receive a participantDisconnected event.


_12
// To disconnect from a Room, we call:
_12
room.disconnect();
_12
_12
// This results in a call to Room.Listener#onDisconnected
_12
private Room.Listener roomListener() {
_12
return new Room.Listener() {
_12
@Override
_12
public void onDisconnected(Room room, TwilioException e) {
_12
Log.d(TAG,"Disconnected from " + room.getName());
_12
}
_12
};
_12
}

As of the 4.0.0 release, the Video SDK will raise notifications when a Room is reconnecting due to a network disruption. A Room reconnection is triggered due to a signaling or media reconnection event.


_18
private Room.Listener roomListener() {
_18
return new Room.Listener() {
_18
_18
/*
_18
* Exception will be either TwilioException.SIGNALING_CONNECTION_DISCONNECTED_EXCEPTION or
_18
* TwilioException.MEDIA_CONNECTION_ERROR_EXCEPTION
_18
*/
_18
@Override
_18
public void onReconnecting(Room room, TwilioException exception) {
_18
Log.v(TAG, "Reconnecting to room: " + room.getName() + ", exception = " + exception.getMessage());
_18
}
_18
_18
@Override
_18
public void onReconnected(Room room) {
_18
Log.v(TAG, "Reconnected to room " + room.getName());
_18
}
_18
};
_18
}

Reconnections in a Peer-to-Peer Room

reconnections-in-a-peer-to-peer-room page anchor

In a Peer-to-Peer Room, each Participant has media connections to all the other Participants in the Room. If all media connections between the LocalParticipant and all other Participants are broken, then the LocalParticipant's Room will enter the reconnecting state until media connectivity with at least one Participant is re-established.


The Programmable Video REST API allows you to control your video applications from your back-end server via HTTP requests. To learn more check out the Programmable Video REST API docs.


We love feedback and questions especially those with helpful debugging information so we can diagnose and respond quickly. When submitting issues or support tickets, it would be great if you add the following:

  • Description - A description of the issue
  • Steps to reproduce - List the steps necessary to reproduce the issue
  • Code - Include any applicable code snippets that would assist in reproduction and troubleshooting
  • Expected Behavior - What you expect to happen
  • Actual Behavior - What actually happens
  • Reproduces How Often - What percentage of the time does it reproduce?
  • Logs - Any log output when the issue occurs. See below for enabling debug level logging.
  • Video Android SDK - The version(s) of the Video Android SDK where this issue is apparent
  • Android Version - The version(s) of Android where this issue is apparent
  • Android Device - The Android device(s) where this issue is apparent
  • Room SID - Room SIDs can be useful for tracing backend issues

After gathering the above information, you can get help in a few ways:


To enable debug level logging, add the following code in your application:


_13
/*
_13
* Set the log level of the Video Android SDK
_13
*/
_13
Video.setLogLevel(LogLevel.DEBUG);
_13
_13
/*
_13
* If your application is experiencing an issue related to a specific
_13
* module, you can set the log level of each of the following modules.
_13
*/
_13
Video.setModuleLogLevel(LogModule.CORE, LogLevel.DEBUG);
_13
Video.setModuleLogLevel(LogModule.PLATFORM, LogLevel.DEBUG);
_13
Video.setModuleLogLevel(LogModule.SIGNALING, LogLevel.DEBUG);
_13
Video.setModuleLogLevel(LogModule.WEBRTC, LogLevel.DEBUG);


Rate this page: