Android - Java/Kotlin
Overview
Follow this step-by-step tutorial to implement the video playback Synchronization SDK.
While the client-side SDK will take care of most of the functionality, in order to make this sample application work, you will need to use the API_KEY provided to you.
Full code samples can be found here
Requirements
To complete this guide successfully the following prerequisites are required:
A Sceenic account
Access key for sync SDK
Authentication
An Access Token
is needed in order to allow a client to connect to a sync group.
Note: It is important that the client application does not request an Access Token directly from the backend. By doing that you risk exposing the API_TOKEN and API_SECRET.
Acquiring an Access Token
curl -iL --request GET --url https://YOUR_CAS_URL/sync/token --header 'auth-api-key: API_KEY' --header 'auth-api-secret: API_SECRET'
The Access Token
is a JWT token - more about jwt you can read - here.
A successful response will look like that:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...."
}
Note: Every Sync Token corresponds to one specific sync group only. To allow two different clients to connect to the same group, the clients need to use the same Access Token
.
Create a project
Open the Android Studio and select New Project from the File menu
Select Empty Activity and click next
Choose Java or Kotlin as your programming language for the project
Configure your project's location, application, and package names
Set the minimum SDK version of the application to 21 or higher
Add the sync SDK library to your project
Create (if it does not exist) in the project a libs directory under the app folder
Add the file wtsyncsdk_v....aar to the libs folder
Edit the application's build.gradle file (in the app folder) with SDK
android {
// Required
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// Required
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude("META-INF/*.kotlin_module")
}
}
dependencies {
implementation files('libs/wtsyncsdk_v....aar')
implementation 'androidx.core:core-ktx:1.7.0'
}
Permissions
Add the following permissions to the AndroidManifest.xml file under the app/src/main folder in the project above the application tag.
<uses-permission android:name = "android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.INTERNET" />
Instantiating the SDK
SDK builder - Call SyncSdkBuilder to instantiate the SDK.
mSyncSdk = new SyncSdk.SyncSdkBuilder()
.accessToken(mAccessToken) // mAccessToken - authorization token
.name(mDisplayName) // mDisplayName - username
.syncListener(this) // this - SyncListener object
.build();
Start synchronization
if (mSyncSdk != null) {
mSyncSdk.startSync();
}
Stop synchronization
if (mSyncSdk != null) {
mSyncSdk.stopSync();
}
Group play video
if (mSyncSdk != null) {
mSyncSdk.groupPlay();
}
Group pause video
if (mSyncSdk != null) {
mSyncSdk.groupPause();
}
Group seek video
if (mSyncSdk != null) {
mSyncSdk.groupSeek(position);
}
Group seek success
if (mSyncSdk != null) {
mSyncSdk.groupSeekSuccess(position);
}
Managing synchronization logic
The synchronization logic is managed using callbacks, using them you will be able to create the interaction you need.
In the sample application, you can see an example for implementing the necessary callbacks
public class MainActivity extends AppCompatActivity implements SyncListener {
...
@Override
public void onClientList(@NotNull List<SyncClient> syncClients) {
// remote sync client joined to the group, update ui using adapter
// update ui with the list of connected clients in the same group
}
@Override
public void onSetPlaybackRate(float rate) {
// setting playback rate
}
@Override
public void onPlaybackFromPosition(long position) {
// playback from position
// player.seekTo(position);
}
@Override
public long onGetPlayerPosition() {
// getting player position
// Implement your logic to extract player position in miliseconds,
// be sure that all clients connected to the same group extracts relevant
// and from the same content timestamps(position)
// return player.getCurrentPosition();
return 0L;
}
@Override
public float onGetPlaybackRate() {
// getting playback rate
// Implement your logic to extract player rate/speed
// return player.speed;
return 0f;
}
@Override
public void onSyncInfo(@NotNull SyncInfo syncInfo) {
// information about synchronization's accuracy and delta
// syncInfo.accuracy 0.0% - 100.0%
// syncInfo.delta starts from 0L and describes how big is delay
// in miliseconds, can be negative value
}
@Override
public void onSyncGroupPlay() {
// received an event onSyncGroupPlay()
// play function should be called if its not playing already
if (!player.isPlaying()) {
player.play();
}
}
@Override
public void onSyncGroupPause() {
// received an event onSyncGroupPause()
// pause function should be called if its still playing
if (player.isPlaying()) {
player.pause();
}
}
@Override
public void onSyncGroupSeek(long position) {
// received an event onSyncGroupSeek(long position) with position parameter
// seek function should be called to the given position
// works with VOD
if (!player.isCurrentWindowLive()) {
player.seekTo(position);
}
// Client should send success seek request every time onSyncGroupSeek called
if (mSyncSdk != null) {
mSyncSdk.groupSeekSuccess(position);
}
}
@Override
public void onSyncDisconnected() {
// client has been disconnected from the group. All connections
// will be closed. Clear ui and data
}
}
Running the application
Once coding is finished, you should be able to run the application in the Android Studio emulator.
You can view the complete Watch Together sample application here
Support
Need technical support? contact us at [email protected].
Last updated
Was this helpful?