Android Integration
The main objective is to write your basic VidyoPlatfrom Connector Android application that could be easily integrated with your business flow.
Environment Setup
To get started with Android Connector SDK, the requirement is an Android Studio & Android SDK. Android Studio is the IDE for creating native Android apps. It includes the Android SDK, which will need to be configured for use in the command line. Android Studio is also used to create Android virtual devices, which are required for the Android emulator.
Installing Android Studio
Download Android Studio from the Android website. More detailed installation instructions can be found in the User Guide.
Installing the Android SDK
Once installed, open Android Studio. The IDE should detect that the Android SDK needs to be installed. In the SDK Components Setup screen, finish installing the SDK. Keep note of the Android SDK Location.

By default, the latest stable SDK Platform is installed, which includes a collection of packages required to target that version of Android.
To install system images and other minor SDK platform packages, you may need to ensure Show Package Details is checked at the bottom of the SDK Manager.

For future reference, the Android SDK can be managed with Android Studio in the Configure » SDK Manager menu of the Android Studio welcome screen or Tools » SDK Manager inside Android projects.
Configuring Command Line Tools
The Android SDK ships with useful command-line tools. Before they can be used, some environment variables must be set. The following instructions are for macOS and Linux. For Windows, check the documentation on setting and persisting environment variables in terminal sessions.
In ~/.bashrc
, ~/.bash_profile
, or similar shell startup scripts, make the following modifications:
Set the
ANDROID_SDK_ROOT
environment variable. This path should be the Android SDK Location used in the previous section.For Mac:
$ export ANDROID_SDK_ROOT=$HOME/Android/sdk
For Linux/Windows:
$ export ANDROID_SDK_ROOT=$HOME/Android/Sdk
Add the Android SDK command-line directories to
PATH
. Each directory corresponds to the category of command-line tool.$ # avdmanager, sdkmanager$ export PATH=$PATH:$ANDROID_SDK_ROOT/tools/bin$ # adb, logcat$ export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools$ # emulator$ export PATH=$PATH:$ANDROID_SDK_ROOT/emulator
Java
Native Android apps are compiled with the Java programming language. Download JDK8 from the download page.
Gradle
Gradle is the build tool used in Android apps and must be installed separately. See the install page for details.
Project Setup
If you already have all the above tools installed, you should be able to get up and running within a few minutes. Let's start from scratch by creating a blank project.


Wait for the Gradle sync to complete. Now we are good to jump into the Connector SDK setup.
Connector SDK Setup
The Connector SDK offers the same APIs on all supported platforms, providing a fast learning curve and enabling rapid development on all device types.
Download & Locate
First of all, we have to Download the latest Connector SDK Package for Android. You can download it under Resources section of VidyoPlatfrom Space or use the following link:
Download and unzip VidyoClient-AndroidSDK package content.
Locate
VidyoClient.aar
under/VidyoClient-AndroidSDK/lib/android/
Copy
VidyoClient.aar
to your project under/app/libs/

Link Connector SDK
In order to link the Connector SDK AAR
Library we have to tell our Gradle sync to to look into /app/libs
a folder and lookup for *.aar
files specifically. Open app/build.gradle
configurations file and apply fileTree
dependency implementation:
implementation fileTree(dir: 'libs', include: ['*.aar'])

Now we are good to start over with Basic Connector SDK implementation.
Connector SDK Implementation
Connector SDK has a very simple API that only requires three basic steps:
When using the client library, the first step is to initialize the Connector SDK
Construct and pass the View where the preview and participants should be rendered.
Connect to the live conference. A developer can specify the portal and room where they want all the live participants to connect.
Setup Android Permissions
Connector SDK requires Android-specific runtime permissions, which we have to request before initializing SDK along with the Basic permissions for Networking.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- RUNTIME PERMISSIONS -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Add those permissions to your AndroidManifest.xml
Now let's add the following code in order to request Runtime Permissions under our MainActivity
:
private static final int PERMISSIONS_REQUEST_CODE = 0x144;
private static final String[] PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermissions();
}
/**
* Verify or Request Runtime Permissions every time before attempting to initialize Connector SDK
*/
private void requestPermissions() {
List<String> permissionsRequired = new ArrayList<>();
for (String permission : PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED)
permissionsRequired.add(permission);
}
if (!permissionsRequired.isEmpty()) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSIONS_REQUEST_CODE);
} else {
onPermissionsAllowed();
}
}
/**
* Here we are safe to initialize a Connector SDK
*/
private void onPermissionsAllowed() {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_CODE) {
onPermissionsAllowed();
}
}

Initialize Connector SDK
Once we have passed through sequential permissions requests (the app will ask for Camera & Audio permissions) we are good to initialize Connector SDK.
ConnectorPkg.initialize();
ConnectorPkg.setApplicationUIContext(this);

Construct Connector API
Connector Object is the main communication instance with the Connector SDK by leveraging all the API calls and managing the SDK Library lifecycle. Base concept APIs that we are going to review in the scope of this Guide:
Construct Connector Object:
new Connector
Update video renderer:
showViewAt
Connect to the call:
connectToRoomAsGuest
Disconnect from the call:
disconnect
Get Connector state:
getState
Manage Connector lifecycle:
setMode
Destroy connector instance:
disable
We are going to create a new connector instance right after SDK initialization. But first of all, let's have a look at the constructor parameters:
Connector(Object viewId,
Connector.ConnectorViewStyle viewStyle,
int remoteParticipants,
String logFileFilter,
String logFileName,
long userData);
viewId
A platform-specific view ID where the VidyoConnector's rendering window will be added as a child window.
viewStyle
Type of the composite renderer which represents the visual style and behaviour.
remoteParticipants
Number of remote participants to composite into the window. Setting the value to 0 (zero) will render the preview only.
logFileFilter
A space-separated (or comma-separated) sequence of names of log levels, each optionally followed by a category.
logFileName
Full path to the file where the log should be stored; otherwise, NULL or empty string, in order to use the default OS-dependent writable path.
userData
Arbitrary user data that can be retrieved later.
Guess we can populate everything except viewId
. For this, we have to create a ViewGroup container and pass it as a viewId
reference. Visit your activity_main.xml
UI layout file and add any kind of ViewGroup expanding full screen.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/video_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Now let's create a Connector Object:
public class MainActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener {
// ...
private Connector mConnector;
private FrameLayout mVideoContainer;
// ...
/**
* Here we are safe to initialize a Connector SDK
*/
private void onPermissionsAllowed() {
ConnectorPkg.initialize();
ConnectorPkg.setApplicationUIContext(this);
mVideoContainer = findViewById(R.id.video_container);
mConnector = new Connector(videoContainer,
Connector.ConnectorViewStyle.VIDYO_CONNECTORVIEWSTYLE_Default,
8,
"warning debug@VidyoClient",
"",
0);
mVideoContainer.getViewTreeObserver().addOnGlobalLayoutListener(this)
}
@Override
public void onGlobalLayout() {
int width = mVideoContainer.getWidth();
int height = mVideoContainer.getHeight();
mConnector.showViewAt(mVideoContainer, 0, 0, width, height);
}
}
In order to render self-view or any remote participant, you have to tell the library your View's dimension and renderer position:
mConnector.showViewAt(mVideoContainer, 0, 0, width, height);
Moreover, you have to do it every time the View's layout has changed or manipulated. In this guide, we'll use a robust OnGlobalLayoutListener
, however, you are good to go with your own solution.
Don't forget to unregister from OnGlobalLayoutListener
updates:
@Override
protected void onDestroy() {
super.onDestroy();
mVideoContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
Host and RoomKey
In the previous tutorial you created a room on your tenant and received a RoomLink:
As you may guess, the following chunk of the above link is your Host value:
And this one is a RoomKey:
bPFCSWVZnb
After we got the necessary parameters (host, roomKey, displayName) we can proceed with joining the call.
Connect to the Call
Before we start executing Connector API let's add some basic interaction UI. We are going to have Connect/Disconnect Button. That's all we need to hop on the call or disconnect. Additionally, we would like to indicate that the call connection is in progress with basic ProgressBar. Modify your activity_main.xml
UI layout file:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/video_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/connect_disconnect_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="24dp"
android:text="Connect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ProgressBar
android:id="@+id/connection_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
In order to connect to the call, you should have your Host
and RoomKey
already prepared as stated in the section above or Getting Started section.
Execute
connectToRoomAsGuest
Connector API and connect to the callExecute
disconnect
Connector API in order to disconnect from the callTo differentiate Connector's Connected|Disconnected state, we'll use
getState
API
// ...
private Button mConnectBtn;
private ProgressBar mConnectionProgress;
// ..
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mVideoContainer = findViewById(R.id.video_container);
mConnectBtn = findViewById(R.id.connect_disconnect_btn);
mConnectBtn.setOnClickListener(this);
mConnectionProgress = findViewById(R.id.connection_progress_bar);
mConnectionProgress.setVisibility(View.GONE);
requestPermissions();
}
// ...
@Override
public void onClick(View view) {
if (view == mConnectBtn) {
boolean isConnected = mConnector.getState() == Connector.ConnectorState.VIDYO_CONNECTORSTATE_Connected;
mConnectionProgress.setVisibility(View.VISIBLE);
mConnectBtn.setEnabled(false);
if (!isConnected) {
mConnectBtn.setText("Connecting...");
mConnector.connectToRoomAsGuest("HOST", "DISPLAY NAME", "ROOM KEY", "ROOM PIN",
new Connector.IConnect() {
@Override
public void onSuccess() {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectBtn.setText("Disconnect");
mConnectionProgress.setVisibility(View.GONE);
});
}
@Override
public void onFailure(Connector.ConnectorFailReason connectorFailReason) {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectionProgress.setVisibility(View.GONE);
Toast.makeText(MainActivity.this, "Connection failed: " + connectorFailReason, Toast.LENGTH_LONG).show();
});
}
@Override
public void onDisconnected(Connector.ConnectorDisconnectReason connectorDisconnectReason) {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectionProgress.setVisibility(View.GONE);
mConnectBtn.setText("Connect");
});
}
});
} else {
mConnectBtn.setText("Disconnecting...");
mConnector.disconnect();
}
}
}
Callbacks
There are three callback functions in the API call above:
onSuccess(): will be fired when connection to the room went successfully. This place is an indicator of the fact that your application has joined the call.
onFailure(): will be fired when connection attempt was made, but something went wrong and your app hasn't joined the call. Reason parameter may provide you with details why connection attempt was not successful.
onDisconnected(): will be fired when your application disconnected from the call.
As you might notice, all the callbacks coming from Connector SDK are routed to the Main UI Thread
with runOnUiThread
Activity's API. It's because the library is executing them from its own Background Thread where you cannot touch or update UI.
Disconnect from the call
Connector disconnect
API has been mentioned earlier, however, the important notice is to properly manage the disconnection state. It's not recommended to wrap the activity during the active conference, therefore, you have to disconnect first and wrap up the connector instance gracefully.
Assume, the user would like to quit the Activity. We have to prevent this action until further disconnection:
private boolean mUserQuitRequest = false;
// ....
@Override
public void onBackPressed() {
if (mConnector.getState() == Connector.ConnectorState.VIDYO_CONNECTORSTATE_Connected) {
mUserQuitRequest = true;
mConnector.disconnect();
} else {
super.onBackPressed();
}
}
// ...
@Override
public void onClick(View view) {
if (view == mConnectBtn) {
boolean isConnected = mConnector.getState() == Connector.ConnectorState.VIDYO_CONNECTORSTATE_Connected;
mConnectionProgress.setVisibility(View.VISIBLE);
mConnectBtn.setEnabled(false);
if (!isConnected) {
mConnectBtn.setText("Connecting...");
mConnector.connectToRoomAsGuest("HOST", "DISPLAY NAME", "ROOM KEY", "ROOM PIN",
new Connector.IConnect() {
@Override
public void onSuccess() {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectBtn.setText("Disconnect");
mConnectionProgress.setVisibility(View.GONE);
});
}
@Override
public void onFailure(Connector.ConnectorFailReason connectorFailReason) {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectionProgress.setVisibility(View.GONE);
Toast.makeText(MainActivity.this, "Connection failed: " + connectorFailReason, Toast.LENGTH_LONG).show();
if (mUserQuitRequest) {
MainActivity.super.onBackPressed();
}
});
}
@Override
public void onDisconnected(Connector.ConnectorDisconnectReason connectorDisconnectReason) {
runOnUiThread(() -> {
mConnectBtn.setEnabled(true);
mConnectionProgress.setVisibility(View.GONE);
mConnectBtn.setText("Connect");
if (mUserQuitRequest) {
MainActivity.super.onBackPressed();
}
});
}
});
} else {
mConnectBtn.setText("Disconnecting...");
mConnector.disconnect();
}
}
}
mUserQuitRequest
will hold the quit request state until onDisconnected
or onFailure
in order to re-test onBackPressed
action.
Manage Lifecycle
You have to tell Connector Object about lifecycle state change so he can manage his internal flow accordingly. setMode
is the proper API to do this.
@Override
protected void onResume() {
super.onResume();
if (mConnector != null)
mConnector.setMode(Connector.ConnectorMode.VIDYO_CONNECTORMODE_Foreground);
}
@Override
protected void onPause() {
super.onPause();
if (mConnector != null)
mConnector.setMode(Connector.ConnectorMode.VIDYO_CONNECTORMODE_Background);
}
Destruct Connector Instance
The last and most important part is the "Connector Object deallocation". Ideally, you have to do this along with the Activity lifecycle to prevent a further memory leak. To sync them together, we'll use onDestroy
Activity's lifecycle callback. At this point, we are insured that mConnector
state is not "Connected" and we are safe to call disable
API.
@Override
protected void onDestroy() {
super.onDestroy();
mVideoContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Destroy connector instance
if (mConnector != null)
mConnector.disable();
}
Last updated