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.
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.
You can get your API_KEY and API_SECRET in your private area, here.
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
if (mSyncSdk != null) {
mSyncSdk.groupSeek(position);
}
mSyncSdk?.groupSeek(position)
Group seek success
if (mSyncSdk != null) {
mSyncSdk.groupSeekSuccess(position);
}
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
}
}
class MainActivity : AppCompatActivity(), SyncListener {
...
override fun onClientList(syncClients: List<SyncClient>) {
// remote client joined to the group, update ui using adapter
// update ui with the list of connected clients in the same group
}
override fun onSetPlaybackRate(rate: Float) {
// setting playback rate
}
override fun onPlaybackFromPosition(position: Long) {
// playback from position
// player.seekTo(position)
}
override fun onGetPlayerPosition(): Long {
// 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()
// Important! In case if content is Http Live Stream
// Value of position shoulb be based on Program-Date-Time tag
return 0L
}
override fun onGetPlaybackRate(): Float {
// getting playback rate
// Implement your logic to extract player rate/speed
// return player.speed
return 0f
}
override fun onSyncInfo(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 fun onSyncGroupPlay() {
// received an event onSyncGroupPlay()
// play function should be called
player.play()
}
override fun onSyncGroupPause() {
// received an event onSyncGroupPause()
// pause function should be called
player.pause()
}
override fun onSyncGroupSeek(position: Long) {
// 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
mSyncSdk?.groupSeekSuccess(position)
}
override fun 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