Twilio migration guide (Android)
This guide walks you through how to migrate your existing Twilio Video implementation to the Vonage Video SDK. Vonage offers two ways to get started: Vonage’s Video API.
Overview
Twilio and Vonage Video APIs have very similar concepts. This starter guide aims to assist you in migrating your video application.
The main difference is that in Twilio you need to create a room SID whereas in Vonage you create a SessionID. You then create authentication tokens which are used on the client side to connect to rooms in Twilio or sessions in Vonage.
The following diagrams detail the main differences:
Get Video SDK credentials
Create a developer Account to access the developer portal. To get started with video you need to create an application. You can follow the create an application guide to obtain your application ID and private key.
Install the SDK
Replace the Twilio video SDK reference in your Gradle file (build.gradle) with the Vonage video SDK.
Thus from implementation 'com.twilio:video-android:7.5.1' to implementation ‘com.opentok.android:opentok-android-sdk:2.27.0’.
Enable required permissions
If not already done, please enable the following permission in the AndroidManifest.xml file:
Authentication
The Vonage Video SDK uses tokens to authenticate users. When generating a token you can set the user’s role (subscriber, publisher, or moderator). Optionally, you can also assign a string of metadata to the token (i.e. to identify the connected client).Please refer to our Token Creation Overview article for options you can use when generating tokens. Tokens are generated on the server-side and sent to the client-side. Visit the Server-side SDKs guides to learn more.
Create a video session
A session is like a room, clients with the same session ID will be able to communicate with each other. Like tokens, sessions are created on the server side.
Please refer to our Creating a session guide to learn more as well as the various configuration options available.
To create a session and generate a token, use one of our server SDKs.
Connect to a video session
To connect a client endpoint to a Vonage Video session you need an application ID, session ID, and token.
These credentials can be retrieved from the Dashboard and hardcoded in the application for development, however for a production environment use the server SDKs to provide the session ID and token (check Basic-Video-Chat project).
Twilio Vonage terminology mapping
| Twilio | Vonage |
|---|---|
| Room | Session |
| Participants | Subscriber(s) + Publisher(s) |
| Tracks | Stream |
| RemoteTracks | Subscribers(s).stream |
| LocalTracks | Publisher(s).stream |
Connecting to a video session
Connecting and managing video streams are done using event handler.
There are three key event listeners you need to implement:
- Session.SessionListener (
private Session mSession;) - PublisherKit.PublisherListener (
private Publisher mPublisher;) - SubscriberKit.SubscriberListener (
private Subscriber mSubscriber;)
SessionListener
The Session.SessionListener methods are used to handle events involving the addition and removal of participants (subscribers and publishers).
This is equivalent to Twilio's Room.Listener event handler.
Below is the structure of the exposed SessionListener interface:
private Session.SessionListener sessionListener = new Session.SessionListener() {
@Override
public void onConnected(Session session) {
Log.d(TAG, "onConnected: Connected to session: " + session.getSessionId());
mPublisher = new Publisher.Builder(MainActivity.this).build();
mPublisher.setPublisherListener(publisherListener);
mSession.publish(mPublisher);
}
@Override
public void onDisconnected(Session session) {
Log.d(TAG, "onDisconnected: Disconnected from session: " + session.getSessionId());
}
@Override
public void onStreamReceived(Session session, Stream stream) {
Log.d(TAG, "onStreamReceived: New Stream Received " + stream.getStreamId() + " in session: " + session.getSessionId());
mSubscriber = new Subscriber.Builder(MainActivity.this, stream).build();
mSubscriber.setSubscriberListener(subscriberListener);
mSession.subscribe(mSubscriber);
}
@Override
public void onStreamDropped(Session session, Stream stream) {
Log.d(TAG, "onStreamDropped: Stream Dropped: " + stream.getStreamId() + " in session: " + session.getSessionId());
}
@Override
public void onError(Session session, OpentokError opentokError) {
Log.e("Session error: " + opentokError.getMessage());
}
};
PublisherListener
The PublisherKit.PublisherListener is used to implement logic to execute based on the creation and end streams.
Below is the structure of the exposed PublisherListener interface:
private PublisherKit.PublisherListener publisherListener = new PublisherKit.PublisherListener() {
@Override
public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
Log.d(TAG, "onStreamCreated: Publisher Stream Created. Own stream " + stream.getStreamId());
}
@Override
public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
Log.d(TAG, "onStreamDestroyed: Publisher Stream Destroyed. Own stream " + stream.getStreamId());
}
@Override
public void onError(PublisherKit publisherKit, OpentokError opentokError) {
Log.e("PublisherKit onError: " + opentokError.getMessage());
}
};
SubscriberListener
The SubscriberKit.SubscriberListener is used to implement logic to execute when a subscriber joins a stream.
Below is the structure of the exposed SubscriberListener interface:
SubscriberKit.SubscriberListener subscriberListener = new SubscriberKit.SubscriberListener() {
@Override
public void onConnected(SubscriberKit subscriberKit) {
Log.d(TAG, "onConnected: Subscriber connected. Stream: " + subscriberKit.getStream().getStreamId());
}
@Override
public void onDisconnected(SubscriberKit subscriberKit) {
Log.d(TAG, "onDisconnected: Subscriber disconnected. Stream: " + subscriberKit.getStream().getStreamId());
}
@Override
public void onError(SubscriberKit subscriberKit, OpentokError opentokError) {
Log.e("SubscriberKit onError: " + opentokError.getMessage());
}
};
Connecting to a session
You will need your APP_ID , SESSION_ID to connect to a video stream.
A TOKEN corresponding to the stream you will like to join is also required.
Twilio
private Room room;
ConnectOptions.Builder connectOptionsBuilder =
new ConnectOptions.Builder(accessToken).roomName(roomName);
room = Video.connect(this, connectOptionsBuilder.build(), roomListener());
Vonage
Session.Builder builder = new Session.Builder(this, APP_ID, SESSION_ID);
mSession = builder.build();
mSession.setSessionListener(sessionListener);
mSession.connect(TOKEN);
Publishing video
Vonage Video SDKs handle video quality tuning automatically, based on network conditions and device capabilities.
That said, you can configure certain properties, such as resolution, frame rate, and audio fallback. A single publisher object can handle both audio and video. You may selectively control audio or video using methods available with the publisher object.
Add publisher
Twilio:
localVideoTrack = LocalVideoTrack.create(this, true, cameraCapturerCompat, LOCAL_VIDEO_TRACK_NAME);
Vonage:
Session.SessionListener() {
@Override
public void onConnected(Session session) {
Log.d(TAG, "onConnected: Connected to session: " + session.getSessionId());
mPublisher = new Publisher.Builder(MainActivity.this).build();
mPublisher.setPublisherListener(publisherListener);
mSession.publish(mPublisher);
}
}
Audio track only
Twilio
localVideoTrack =
LocalVideoTrack.create(this, false, cameraCapturerCompat, LOCAL_VIDEO_TRACK_NAME);
Vonage:
mPublisher = new Publisher.Builder(this).name(mUsername)
.videoTrack(false)
.build();
Video track only
Twilio:
localAudioTrack = LocalAudioTrack.create(this, false, LOCAL_AUDIO_TRACK_NAME);
Vonage:
mPublisher = new Publisher.Builder(this).name(mUsername)
.audioTrack(false)
.build();
Unpublish from session
Twilio:
localParticipant.unpublishTrack(localVideoTrack);
Vonage:
mSession.unpublish(mPublisher);
Mute Publisher Audio
Twilio:
localAudioTrack.enable(false);
Vonage:
mPublisher.setPublishAudio(false);
UnMute Publisher Audio
Twilio:
localAudioTrack.enable(true);
Vonage:
mPublisher.setPublishAudio(true);
Mute Publisher Video
Twilio:
localVideoTrack.enable(false);
Vonage:
mPublisher.setPublishVideo(false);
UnMute Publisher Video
Twilio:
localVideoTrack.enable(true);
Vonage:
mPublisher.setPublishVideo(true);
Subscribe to a stream
When a remote participant (subscriber) connects to a session, the Session.SessionListener.onStreamReceived() callback is invoked with corresponding stream object.
Twilio:
@Override
public void onConnected(Room room) {
localParticipant = room.getLocalParticipant();
setTitle(room.getName());
for (RemoteParticipant remoteParticipant : room.getRemoteParticipants()) {
addRemoteParticipant(remoteParticipant);
break;
}
}
Vonage:
@Override
public void onStreamReceived(Session session, Stream stream) {
Log.d(TAG, "onStreamReceived: New Stream Received " + stream.getStreamId() + " in session: " + session.getSessionId());
mSubscriber = new Subscriber.Builder(MainActivity.this, stream).build();
mSubscriber.setSubscriberListener(subscriberListener);
mSession.subscribe(mSubscriber);
}
Disconnecting from a session
Twilio:
room.disconnect()
Vonage:
mSession.disconnect()
onPause() and onResume() methods
Vonage:
@Override
protected void onPause() {
super.onPause();
if (mSession != null) {
mSession.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mSession != null) {
mSession.onResume();
}
}
Ideally onPause() and onResume() should be implemented in the MainActivity Class.
Screen sharing
An example app for screen sharing.
Text chat app
An example app for sending text.
More Info
- Sample Gradle file.
- Sample Applications at Android sample apps.
- Best practices for building Video applications.
- Vonage Video API Android SDK
- Server side SDKs