Getting Started with Zoom's Android Video SDK
Tags: zoom, sdk
Published: 2023-08-08 16:13:07

## Introduction

The Zoom Video SDK for Android allows you to build custom video meeting applications with access to raw video and audio data, enabling highly-interactive, custom user experiences. When we say "custom", it lets you customise almost everything to cater your needs. It helps you build the product with your brand.

The goal of this article is to get you started with Video SDK in Android platform. We'll cover:

- SDK contents
- Pre-requisites
- JWT Authentication
- Project structure
- Init SDK & Join/Leave Session
- Video, Audio, & Screen-Share Functionality

## SDK contents

There are three .aar files packaged in the Android SDK downloaded from Zoom marketplace. 

- mobilertc.aar : Consists of Zoom UI components
- video-effects.aar: Used when you implement Virtual Background feature
- zm-annoter.aar: Used when you use annotation service

In our project, I will be using "java" as the primary language of coding. We shall be demonstrating the basic abilities like audio, video and screenshare and hence I will be importing only the mobilertc.aar package as a module in main project.

## Pre-requisites

To build the app, you must have:

- Zoom Video SDK package for Android downloaded from marketplace
- Android Studio
- SDK Key and secret values
- A physical Android device with Android API Level 21+
- Experience building Android Apps

Note: This tutorial is built on top of v1.8.5 in Java.

## JWT Authentication

JWT authorisation is used in the SDK. The payload information is provided [here](https://developers.zoom.us/docs/video-sdk/auth/).

To begin with, let's construct the JWT token using a webapp and invoke the HTTP POST request in our Android application. It is advisable to host the JWT token server in your own web server due to security reasons. The webapp code looks like below.

```
app.post('/', (req, res) => {

  const iat = Math.round(new Date().getTime() / 1000) - 30;
  const exp = iat + 60 * 60 * 2

  const oHeader = { alg: 'HS256', typ: 'JWT' }

  const oPayload = {
    app_key: process.env.ZOOM_VIDEO_SDK_KEY,
    tpc: req.body.sessionName,
    role_type: req.body.role,
    user_identity: req.body.userIdentity,
    session_key: req.body.sessionKey,
    geo_regions: req.body.geoRegions,
    cloud_recording_option: req.body.cloudRecordingOption,
    cloud_recording_election: req.body.cloudRecordingElection,
    version: 1,
    iat: iat,
    exp: exp
  }

  const sHeader = JSON.stringify(oHeader)
  const sPayload = JSON.stringify(oPayload)
  const signature = KJUR.jws.JWS.sign('HS256', sHeader, sPayload, process.env.ZOOM_VIDEO_SDK_SECRET)

  res.json({
    signature: signature
  })
})
```

The complete web app code is located here: https://github.com/ajitha-zoom/videosdk-demo-endpoint

Let us now invoke the HTTP POST api from our Android application using following payload. The response shall have the JWT signature.

```
    private String JSON_PAYLOAD = "{\"sessionName\":\"" + SAMPLE_SESSION_NAME +
            "\",\"role\":" + SAMPLE_ROLE +
            ",\"userIdentity\":\"" + SAMPLE_USER_IDENTITY +
            "\",\"sessionKey\":\"" + SAMPLE_SESSION_PWD +
            "\",\"geoRegions\":\"US,AU,CA,IN,CN,BR,MX,HK,SG,JP,DE,NL\"," +
            "\"cloudRecordingOption\":1,\"cloudRecordingElection\":0}";
```

The response shall be parsed as shown below to retrieve the JWT signature

```
JSONObject jsonObject = null;
try {
    jsonObject = new JSONObject(result);
} catch (JSONException e) {
    throw new RuntimeException(e);
}]

// Retrieve the "signature" parameter
String signature = jsonObject.optString("signature");
jsa.onPostExecution(signature);
```

## Project structure

To create a new project,
- Open Android studio
- File -> New -> New Project -> Choose "No Activity"
- Choose Language as "java" and Build configuration as "Groovy DSL" and press "finish"
- Create a new folder "mobilertc" and place the mobilertc.aar package inside the folder. Also copy the following contents inside mobilertc/build.gradle


```
configurations.create("default")
artifacts.add("default", file('mobilertc.aar'))

dependencies.add("default","androidx.security:security-crypto:1.1.0-alpha03")
dependencies.add("default","com.google.crypto.tink:tink-android:1.5.0")
dependencies.add("default","androidx.appcompat:appcompat:1.3.0")
```

- Once done, the project structure shall look like below:

![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w477g74pg7pbdm7q14a.png)

- Include the mobilertc package in settings.gradle and build.gradle inside your application folder.

settings.gradle
```
include ':mobilertc'
```

build.gradle
```
implementation project(':mobilertc')
```

Since we created project with "No Activity", the source folder shall be empty. Right on the package folder inside "java" and create a empty activity "MainActivity", select "java" as language and set it as a launcher activity for the project. 

For building our project, I have used four activity screens.
- MainActivity : Launcher activity showing a "join" button.
- JoinSessionActivity: To enter "session" details and join
- IntegrationActivity: To help in navigation in and out of application during the screen-share
- MeetingActivity: The in-meeting screen

I have also created a service called "NotificationService" which is our foreground service created during call.

We need to add the necessary permissions required for the project in the AndroidManifest.xml file. The manifest file shall look like here: https://github.com/ajitha-zoom/video-sdk-android/blob/main/app/src/main/AndroidManifest.xml

## Init SDK & Join/Leave Session

In order to initialise SDK, we need to use the intialize method with the InitParams.

```
ZoomVideoSDKInitParams params = new ZoomVideoSDKInitParams();
params.domain = "zoom.us";
params.enableLog = true;
params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryMode.ZoomVideoSDKRawDataMemoryModeHeap;
params.audioRawDataMemoryMode = ZoomVideoSDKRawDataMemoryMode.ZoomVideoSDKRawDataMemoryModeHeap;
params.shareRawDataMemoryMode = ZoomVideoSDKRawDataMemoryMode.ZoomVideoSDKRawDataMemoryModeHeap;

int ret = ZoomVideoSDK.getInstance().initialize(this.getApplicationContext(), params);
```

The initialisation can be verified using the return code.

```
if (ret != ZoomVideoSDKErrors.Errors_Success) {
    //Failure
} else {
    //Success
}
```

Once you initialise the SDK correctly, you will be able to call the SDK functions. Android application requires end user to accept all the necessary permission. So, we need to allow the end user to accept all permissions before attempting to join a session. The same shall be done using the ActivityCompat.requestPermissions() method. To join a session, we need to supply the session context with audio option, video option and JWT token. I have initialised the sessionContext as shown below.

```
ZoomVideoSDKSessionContext sessionContext=new ZoomVideoSDKSessionContext();

/* ------------ SET AUDIO OPTIONS ------------ */
ZoomVideoSDKAudioOption audioOption=new ZoomVideoSDKAudioOption();
audioOption.connect=true;
audioOption.mute=false;
audioOption.isMyVoiceInMix=true;
sessionContext.audioOption=audioOption;

/* ------------ SET VIDEO OPTIONS ------------ */
ZoomVideoSDKVideoOption videoOption=new ZoomVideoSDKVideoOption();
videoOption.localVideoOn=true;
sessionContext.videoOption=videoOption;

/* ------------ VALIDATE INPUTS ------------ */
userName = nameEdit.getText().toString();
if (TextUtils.isEmpty(userName)) {
    userName = Build.MODEL;
}

sessionName = sessionEditText.getText().toString().toLowerCase().trim();

if (TextUtils.isEmpty(sessionName)) {
    Toast.makeText(this, "Session name is empty", Toast.LENGTH_LONG).show();
    return;
}
//Required
sessionContext.sessionName = sessionName;
sessionContext.userName = userName;

password = passwordEdit.getText().toString();
//Optional
sessionContext.sessionPassword = password;

/* ------------ GENERATE JWT ------------ */
JWTGenerator jwtGenerator = new JWTGenerator(this);
jwtGenerator.execute();

.
.
//after retrieving the token
sessionContext.token = token;

/* ------------ JOIN SESSION ------------ */
ZoomVideoSDKSession session=ZoomVideoSDK.getInstance().joinSession(sessionContext);
```

If the "session" is not null, you have successfully created a new videosdk session.

To leave a created session,
```
ZoomVideoSDK.getInstance().leaveSession(true);
```

## Video, Audio, & Screen-Share Functionality

Let's begin to add the basic functionality. The UI screens shall be created as per your convenience. For receiving the session related events and user related events, we need to implement "[ZoomVideoSDKDelegate](https://marketplacefront.zoom.us/sdk/custom/android/us/zoom/sdk/ZoomVideoSDKDelegate.html)" in our MeetingActivity.

I have designed three buttons in my meeting screen "Video", "Audio" & "Screen share" button.

### Video 

To turn on/off the video of self during a session,

```
public void onClickVideo(View view) {
    ZoomVideoSDKUser zoomSDKUserInfo = session.getMySelf();
    if (null == zoomSDKUserInfo) return;
    if (zoomSDKUserInfo.getVideoStatus().isOn()) {  
     ZoomVideoSDK.getInstance().getVideoHelper().stopVideo();
    } else {
     ZoomVideoSDK.getInstance().getVideoHelper().startVideo();
    }
}
```

In order to access the remote participant's video, we need to retrieve the user's canvas and then render the video in the ZoomVideoSDKVideoView.

```
zoomCanvas = new ZoomVideoSDKVideoView(this, false);
..
..
int ret = user.getVideoCanvas().subscribe(zoomCanvas, aspect);
```

To remove the remote participants video, we need to unsubscribe.

```
user.getVideoCanvas().unSubscribe(zoomCanvas);
```

When the users video state is changed, the corresponding delegate method shall be called and we shall update the UI accordingly. 

```
public void onUserVideoStatusChanged(ZoomVideoSDKVideoHelper videoHelper, List<ZoomVideoSDKUser> userList)
```

### Audio

Before trying to turn on/off the audio, we need to start the audio. Only after starting, we would be allowed to mute/unmute the audio of self.

```
public void onClickAudio(View view) {
    ZoomVideoSDKUser zoomSDKUserInfo = session.getMySelf();
    if (zoomSDKUserInfo.getAudioStatus().getAudioType() == ZoomVideoSDKAudioStatus.ZoomVideoSDKAudioType.ZoomVideoSDKAudioType_None) {
        ZoomVideoSDK.getInstance().getAudioHelper().startAudio();
    } else {
        if (zoomSDKUserInfo.getAudioStatus().isMuted()) {
            ZoomVideoSDK.getInstance().getAudioHelper().unMuteAudio(zoomSDKUserInfo);
        } else {
            ZoomVideoSDK.getInstance().getAudioHelper().muteAudio(zoomSDKUserInfo);
        }
    }
}
```

When the remote users audio states are changed, the corresponding delegate methods shall be invoked.

```
public void onUserAudioStatusChanged(ZoomVideoSDKAudioHelper audioHelper, List<ZoomVideoSDKUser> userList)
```

### Screen-Share

In order to use screen-share there are pre-requisites:
- Permissions to be accepted for using MediaProjectionManager
- Screen overlay permission for creating a "Stop share" button
- A running foreground service (in latest versions of Android)

Once the above are achieved, then we can simply invoke the startScreenShare in the ShareHelper.

```
int ret = ZoomVideoSDK.getInstance().getShareHelper().startShareScreen(data);
if (ret == ZoomVideoSDKErrors.Errors_Success) {
    //do something
}
```

Screen sharing can be stopped using,

```
ZoomVideoSDK.getInstance().getShareHelper().stopShare();
```

Remote participants screen sharing can be subscribed and unsubscribed similar to their video using share canvas.

```
user.getShareCanvas().subscribe(zoomCanvas, ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original);
```

and 

```
currentShareUser.getShareCanvas().unSubscribe(zoomCanvas);
```

When the remote users share status is changed, the corresponding delegate method shall be triggered:

```
public void onUserShareStatusChanged(ZoomVideoSDKShareHelper shareHelper, ZoomVideoSDKUser userInfo, ZoomVideoSDKShareStatus status)
```

## Summary

Developing basic functionalities using video sdk is very simple and can be achieved with few lines of code. There are many more features in video-sdk like accessing raw data, cloud recording, live streaming, chat, transcriptions etc., The possibilities are exponential.

Complete source code for above tutorial can be found here: https://github.com/ajitha-zoom/video-sdk-android