# Android - Java/Kotlin

## Overview <a href="#android-javaandkotlin-overview" id="android-javaandkotlin-overview"></a>

Follow this step-by-step tutorial to implement the Watch Together video chat sample application.

While the client-side application will take care of most of the functionality, in order to make this sample application work, you will need to get an access token from the [Cluster Authentication Server](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-api-references/cluster-authentication-service-reference-cas-2) (CAS).

* To better understand the Watch Together architecture have a look at this guide - [Watch Together overview](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-watch-together-overview)
* Have a look at the [Authentication overview](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-overview)
* The full code sample can be found here - Android full code sample [Java ](https://bitbucket.org/svmt/samplewatchtogether-java-2.0/src/master/)or [Kotlin](https://bitbucket.org/svmt/samplewatchtogether-kotlin-2.0/src/master/)

## Requirements <a href="#android-javaandkotlin-requirements" id="android-javaandkotlin-requirements"></a>

To complete this guide successfully the following prerequisites are required:

* [Android Studio](https://developer.android.com/studio)

## Authentication

An Access Token is needed in order to allow a client to connect to a Session.

{% hint style="danger" %}
**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.
{% endhint %}

* To learn how to acquire an Access Token please look at the [Cluster Authentication Server](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-api-references/cluster-authentication-service-reference-cas-2) (CAS) reference
* To simplify the tutorial, in the section below you can see an example of getting an Access Token

### Acquiring an Access Token

{% tabs %}
{% tab title="cUrl(Bash)" %}

```bash
curl -iL --request GET --url https://YOUR_CAS_URL/stream/token/v2/ --header 'auth-api-key: API_KEY' --header 'auth-api-secret: API_SECRET'
```

{% endtab %}
{% endtabs %}

The`Access Token`is a JWT token - more about JWT you can read - [here](https://en.wikipedia.org/wiki/JSON_Web_Token).

A successful response will look like that:

```
{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...."
}
```

{% hint style="info" %}
You can get your API\_KEY and API\_SECRET in your private area, [here](https://media.sceenic.co/).
{% endhint %}

{% hint style="warning" %}
**Note:** Every Streaming Token corresponds to one specific Session only. To allow two different clients to connect to the same Session, the clients need to use the same `Access Token`.
{% endhint %}

### Going to production <a href="#going-to-production" id="going-to-production"></a>

To go to production you will need to implement your own authentication server. Using the server the Access Token will be shared to your various clients (Web, Android, and iOS). With this valid Access Token you will be able to use the service.

For that you will need:

* API\_KEY, and API\_SECRET - can be retrieved in your private area once you [login](https://media.sceenic.co/)
* Your own working authentication server - [Authentication overview](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-overview)

## Creating a new project <a href="#android-javaandkotlin-creatinganewproject" id="android-javaandkotlin-creatinganewproject"></a>

* Open 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 minimum **SDK** version of the application to **23** or higher

## Adding Watch Together Android SDK library to the project <a href="#android-javaandkotlin-addingwatchtogetherandroidsdklibrarytotheproject" id="android-javaandkotlin-addingwatchtogetherandroidsdklibrarytotheproject"></a>

* Create (if it does not exist) in the project **libs** directory under the **app** folder
* Take the downloaded file **wtsdk\_v....aar** and put it into the **libs** folder
* Edit application's **build.gradle** file (in the app folder) with SDK

{% tabs %}
{% tab title="Build.gradle" %}

```
dependencies {	
    implementation files('libs/wtsdk_v....aar')	
}
```

{% endtab %}
{% endtabs %}

If you are using `android.enableJetifier=true` to automatically convert third-party libraries to use AndroidX, please add this line `android.jetifier.blacklist=wsdk_v2.0.4.aar` to your `gradle.properties` file.

{% hint style="warning" %}
If this line is not there the WT library will not compile
{% endhint %}

{% tabs %}
{% tab title="gradle.properties file" %}

```kotlin
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true

# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
android.jetifier.blacklist=sdk-release.aar

```

{% endtab %}
{% endtabs %}

### Adding dependencies <a href="#android-javaandkotlin-addingdependencies" id="android-javaandkotlin-addingdependencies"></a>

* Modify the **build.gradle** file (in the app folder) with SDK dependencies, once modified it should look as follows:

{% tabs %}
{% tab title="Java" %}

```java
android {
...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version'
    ...

	//Watch Together SDK library
    implementation files('libs/wtsdk_v....aar')	
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
android {
...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version'
    implementation 'androidx.core:core-ktx:1.2.0' 
...
    
	//Watch Together SDK library
    implementation files('libs/wtsdk_v....aar')	
}
```

{% endtab %}
{% endtabs %}

* Sync and Rebuild the project
  * If the Sync and Rebuild was executed successfully, the Watch Together classes and functions should be available in the project

### Granting access to camera and microphone <a href="#android-javaandkotlin-grantingaccesstocameraandmicrophone" id="android-javaandkotlin-grantingaccesstocameraandmicrophone"></a>

Using the device Audio and Video requires permissions to be granted from the user and some code that will allow the application to work well under different scenarios.

* Add the following permissions to the **AndroidManifest.xml** file under the **app/src/main** folder in the project above the application tag.

{% tabs %}
{% tab title="" %}

```markup
<uses-feature android:name = "android.hardware.camera" />
<uses-feature android:name = "android.hardware.camera.autofocus" />
<uses-feature
    android:glEsVersion = "0x00020000"
    android:required = "true" />
<uses-permission android:name = "android.permission.CAMERA" />
<uses-permission android:name = "android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name = "android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name = "android.permission.RECORD_AUDIO" />
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.INTERNET" />
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The permissions should be validated before every connect of a client to a session.
{% endhint %}

## Sample application UI <a href="#android-javaandkotlin-sampleapplicationui" id="android-javaandkotlin-sampleapplicationui"></a>

The sample application has a UI element that needs to be handled to allow the proper presentation of the streams and stream properties.

* Use a view container in the application’s resource layout file to display videos. The sample application demonstrates how to manage videos with `RecyclerView` container
* For rendering videos, the SDK provides the `VideoRenderer` class for use in the application’s layout

  ```
  <?xml version="1.0" encoding="utf-8"?>
  <android.support.constraint.ConstraintLayout
  ...

  <com.wt.sdk.VideoRenderer
      android:id="@+id/video_renderer"
      android:layout_width="120dp"
      android:layout_height="160dp" />
  ```
* Initialize Session object with `SessionBuilder` class

{% tabs %}
{% tab title="Java" %}

```java
// Host class of Session object should implement or have interface SessionListener
mSession = new Session.SessionBuilder(this)           // this - SessionListener object   
                    .setReconnectListener(this)       // this - ReconnectListener object
                    .setConnectionListener(this)      // this - ConnectionListener object
                    .build(this);                     // this - Android context
                    
mSession.setDisplayName(mDisplayName);                // optional 
mSession.setEnableStats(isEnableStats);               // isEnableStats - enable stats received                           
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// Host class of Session object should implement or have interface SessionListener
mSession = Session.SessionBuilder(this)             // this - SessionListener object
                    .setReconnectListener(this)     // this - ReconnectListener object
                    .setConnectionListener(this)    // this - ConnectionListener object
                    .build(this)                    // this - Android context
                    
                    
mSession?.setDisplayName(mDisplayName)              // optional            
mSession?.isEnableStats = isEnableStats             // isEnableStats - enable stats received
```

{% endtab %}
{% endtabs %}

* Start camera preview - can be called without the Session’s url and the `Access Token`

{% tabs %}
{% tab title="Java" %}

```java
mSession.startCameraPreview();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
mSession?.startCameraPreview()
```

{% endtab %}
{% endtabs %}

* Connecting to the Session using the Session object requires a Session’s URL and a valid Streaming Token to be available before connecting. The `connect()` function establishes a connection to the Session with the audio and video tracks inside `MediaStream` object

{% tabs %}
{% tab title="Java" %}

```java
// String parameter sessionId should be passed in the function connect.
mSession.connect(mToken);               // mToken - authorization token
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// String parameter sessionId should be passed in the function connect.
mSession?.connect(mToken)               // mToken - authorization token
```

{% endtab %}
{% endtabs %}

* It is possible connect as different types of participants:
  * FULL\_PARTICIPANT - publishes Audio and Video to the session and Subscribes to all other participants Audio and Video in the Session
  * VIEWER - Subscribes to all other participants Audio and Video in the Session
  * AV\_BROADCASTER - Publishes Audio and Video to the Session
  * A\_BROADCASTER - Publishes only Audio to the Session
* In the case you would like to connect as a Viewer do the following:

{% tabs %}
{% tab title="Java" %}

```java
// String parameter sessionId should be passed in the function connectAsViewer.
mSession.connect(mToken, mParticipantType);  // mParticipantType - participant's connection type
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
// String parameter sessionId should be passed in the function connectAsViewer.
mSession?.connect(mToken, mParticipantType)   // mParticipantType - participant's connection type
```

{% endtab %}
{% endtabs %}

## Managing Session logic <a href="#android-javaandkotlin-managingsessionlogic" id="android-javaandkotlin-managingsessionlogic"></a>

To manage the session's logic we provided several callbacks that will allow you to customize the interactions as you need.

* The **SessionListener** interface, which the **MainActivity** implements, will allow you to control the flow of logic of the **Session** you are managing

{% tabs %}
{% tab title="Java" %}

```java
public class MainActivity extends AppCompatActivity implements SessionListener {
   ...
   
    @Override
    public void onConnected(@NonNull List<? extends Participant> list) {
        // client has been connected to the session with the unique sessionId and participants already in the Session
    }

    @Override
    public void onDisconnected() { 
        // client has been disconnected from the session. All connections will be closed.
        // clear ui and data  
        finish() // Close MainActivity page      
    }
    
    @Override
    public void onError(SessionError error) {
        // You can implement error handling here. Check API rferences for possible errors.
    }
    
    @Override
    public void onLocalParticipantJoined(@Nullable Participant participant) {
        // Camera preview started, local stream created, update UI  
        if (mParticipantAdapter != null) {
            mParticipantAdapter.addLocalParticipant(participant);
        }
    }

    @Override
    public void onRemoteParticipantJoined(@Nullable Participant participant) {
        // remote participant joined to the session, update ui.
        // create addParticipant method in the ParticipantsAdapter as in the sample code
        if (mParticipantAdapter != null) {
            mParticipantAdapter.addRemoteParticipant(participant);
        }
    }

    @Override
    public void onUpdateParticipant(@Nullable String participantId, @Nullable Participant participant) {
        // participant update the session, update ui
        if (mParticipantAdapter != null) {
            mParticipantAdapter.updateParticipant(participantId, participant);
        }
    }

    @Override
    public void onRemoteParticipantLeft(@Nullable String participantId) {
        // remote participant left the session, update ui
        if (mParticipantAdapter != null) {
            mParticipantAdapter.removeParticipant(participantId);
        }
    }

    @Override
    public void onParticipantMediaStateChanged(@Nullable String participantId, MediaType mediaType,
        MediaState mediaState) {
        // Method is triggered when remote participant disabled/enabled (mediastate) it's audio/video (mediaType).
        // On UI it can be reflected with this callback
        if (mParticipantAdapter != null) {
            mParticipantAdapter.updateParticipantMedia(participantId, mediaType, mediaState);
        }
    }

    @Override
    public void onMessageReceived(@Nullable String participantId, @Nullable String message) {
        // The method is receiving messages from remote participants into the current room
        Toast.makeText(this, "participant=$participant, message=$message", Toast.LENGTH_LONG).show()
    }
   
    @Override
    protected void onPause() {
        // Disconnect from the session
        mSession.disconnect();
    }

    @Override
    public void onBackPressed() {
        // Disconnect from the session
        mSession.disconnect();
    }
    
    @Override
    protected void onDestroy() {
        // Clear participants and publishers
        mParticipantAdapter.clearParticipants();
        super.onDestroy();
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainActivity : AppCompatActivity(), SessionListener {
    ...
    
    override fun onConnected(participants: List<Participant>) {
        // client has been connected to the session with the unique sessionId and publishers already in the Session
    }
        
    override fun onDisconnected() {
        // client has been disconnected from the session. All connections will be closed.
        // clear ui and data  
        finish() // Close MainActivity page
    }
    
    override fun onError(error: SessionError) {
        // You can implement error handling here. Check API rferences for possible errors.
    }
    
    override fun onLocalParticipantJoined(participant: Participant) {
        // Camera preview started, local stream created, update UI  
        mParticipantAdapter?.addLocalParticipant(participant)
    }

    override fun onRemoteParticipantJoined(participant: Participant) {
        // remote participant joined to the session, update ui.
        // create addParticipant method in the ParticipantsAdapter as in the sample code
        mParticipantAdapter?.addRemoteParticipant(participant)
    }

    override fun onUpdateParticipant(participantId: String, participant: Participant) {
        // participant update the session, update ui
        mParticipantAdapter?.updateParticipant(participantId, participant)
    }

    override fun onRemoteParticipantLeft(participantId: String) {
        // remote participant left the session, update ui
        mParticipantAdapter?.removeParticipant(participantId)
    }
    
    override fun onParticipantMediaStateChanged(
        participantId: String,
        mediaType: MediaConfiguration.MediaType?,
        mediaState: MediaConfiguration.MediaState?
    ) {
        // Method is triggered when remote participant disabled/enabled (mediastate) it's audio/video (mediaType).
        // On UI it can be reflected with this callback
        mParticipantAdapter?.updateParticipantMedia(participantId, mediaType, mediaState)
    }
    
    override fun onMessageReceived(participantId: String, message: String) {
        // The method is receiving messages from remote participants into the current room
        Toast.makeText(applicationContext, "participant=$participant, message=$message", Toast.LENGTH_LONG).show()
    }

    override fun onPause() {
        // Disconnect from the session
        mSession?.disconnect()
    }
    
    override fun onBackPressed() {
        // Disconnect from the session
        mSession?.disconnect()
    }

    override fun onDestroy() {
        // Clear participants and publishers
        mParticipantAdapter?.clearParticipants()
        super.onDestroy()
    }

}
```

{% endtab %}
{% endtabs %}

## Managing Reconnection logic

To manage the reconnect session's logic we provide several callbacks and will allow you to customize the interactions you need.

* The SessionReconnectListener interface, which the MainActivity implements in the sample application, will allow you to control the flow of logic of the **Reconnect** you are managing

{% tabs %}
{% tab title="Java" %}

```java
public class MainActivity extends AppCompatActivity implements SessionReconnectListener {
   ...
    
    @Override
    public void onParticipantReconnecting(final String participantId) {
        // callback which triggers when remote participant loses network 
        // participantId - participant's identificator for updating
        mParticipantAdapter.progressConnection(participantId, true);
    }

    @Override
    public void onParticipantReconnected(String participantId, String oldParticipantId) { 
        // callback with triggers when remote participant network resumes
        // oldParticipantId -  identificator old participant for updating
        // participantId - participant's identificator for updating
        mParticipantAdapter.progressConnection(oldParticipantId, false);     
    }
}

```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainActivity : AppCompatActivity(), SessionReconnectListener {
    ...
    
    override fun onParticipantReconnecting(
        participantId: String
    ) {
        // callback which triggers when remote participant loses network 
        // participantId - participant's identificator for updating
        mParticipantAdapter?.progressConnection(participantId, true)
    }
        
    override fun onParticipantReconnected(
        participantId: String,
        oldParticipantId: String
    ) {
        // callback with triggers when remote participant network resumes
        // oldPublisherId -  identificator old participant for updating
        // participantId - participant's identificator for updating
        mParticipantAdapter?.progressConnection(oldParticipantId, false)
    }
}
```

{% endtab %}
{% endtabs %}

## Managing Connection states logic

To manage the connection states session's logic we provided several callbacks and will allow you to customize the interactions you need.

* The SessionConnectionListener interface, which the MainActivity implements in the sample application, will allow you to control the flow of logic of the **Connection states** you are managing

{% tabs %}
{% tab title="Java" %}

```java
public class MainActivity extends AppCompatActivity implements SessionConnectionListener {
    ...
    
    @Override
    public void onLocalConnectionLost() {
        // callback with triggers when local participant connection lost
    }
    
    @Override
    public void onLocalConnectionResumed() {
        // callback with triggers when local participant connection resumed
    }
    
    @Override
    public void onRemoteConnectionLost(String participantId) {
        // callback with triggers when remote participant connection lost
        // participantId - identificator that participant by id losing connection
        if (mParticipantAdapter != null) {
            mParticipantAdapter.remoteParticipantConnectionLost(participantId);
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainActivity : AppCompatActivity(), SessionConnectionListener {
    ...
    
    override fun onLocalConnectionLost() {
        // callback with triggers when local participant connection lost
    }
    
    override fun onLocalConnectionResumed() {
        // callback with triggers when local participant connection resumed
    }
    
    override fun onRemoteConnectionLost(participantId: String?) {
        // callback with triggers when remote participant connection lost
        // participantId - identificator that participant by id losing connection
        mParticipantAdapter?.remoteParticipantConnectionLost(participantId)
    }
}
```

{% endtab %}
{% endtabs %}

## Enable/Disable Audio or Video

* Bind the Participant view to the Participant data in the **ParticipantsAdapter** class

{% tabs %}
{% tab title="Java" %}

```java
    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {
        final Participant participant = mParticipants.get(viewHolder.getAdapterPosition());
        if (participant != null) {
            participant.setRenderer(viewHolder.videoRenderer);
            participant.enableStats();
            participant.setParticipantStatsListener(new OnParticipantStatsListener() {
                @Override
                public void onStats(@Nullable JSONObject jsonStats,
                    @NotNull Participant participant) {
                    // The callback with json data about connection quality for audio and video
                    try {
                        if (jsonStats != null) {
                            jsonStats.get("audioAvg")          // 0 - 4.5 value
                            jsonStats.get("audioQosMos")       // Value of quality {BAD, GOOD, EXCELLENT}
                            jsonStats.get("videoAvg")          // 0 - 4.5 value
                            jsonStats.get("videoQosMos")       // Value of quality {BAD, GOOD, EXCELLENT}
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
            viewHolder.mic.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    if (participant.isAudioEnabled()) {
                        participant.disableAudio();
                    } else {
                        participant.enableAudio();
                    }
                    notifyItemChanged(position, participant);
                }
            });
            viewHolder.cam.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    if (participant.isVideoEnabled()) {
                        participant.disableVideo();
                    } else {
                        participant.enableVideo();
                    }
                    notifyItemChanged(position, participant);
                }
            });
            // Update microphone and camera UI icons according to Participant's Audio and Video track state
            viewHolder.connectionState.setVisibility(participant.isConnectionLost() ? View.VISIBLE : View.GONE);
            viewHolder.layoutProgress.setVisibility(participant.isProgressReconnection() ? View.VISIBLE : View.GONE);
            viewHolder.mic.setBackgroundResource(participant.isAudioEnabled() ? R.drawable.ic_mic_on : R.drawable.ic_mic_off);
            viewHolder.cam.setBackgroundResource(participant.isVideoEnabled() ? R.drawable.ic_video_on : R.drawable.ic_video_off);

            viewHolder.name.setText(participant.getName());
      }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        val participant = mParticipants[viewHolder.adapterPosition]

        participant.setRenderer(viewHolder.videoRenderer)
        participant.enableStats()
        participant.setParticipantStatsListener(object : OnParticipantStatsListener {
            override fun onStats(jsonStats: JSONObject?, participant: Participant) {
                // The callback with json data about connection quality for audio and video
                jsonStats?.get("audioAvg")          // 0 - 4.5 value
                jsonStats?.get("audioQosMos")       // Value of quality {BAD, GOOD, EXCELLENT}
                jsonStats?.get("videoAvg")          // 0 - 4.5 value
                jsonStats?.get("videoQosMos")       // Value of quality {BAD, GOOD, EXCELLENT}
            }
        })
        
        viewHolder.mic.setOnClickListener {
            if (participant.isAudioEnabled) {
                participant.disableAudio()
            } else {
                participant.enableAudio()
            }
            notifyItemChanged(position, participant)
        }
        viewHolder.cam.setOnClickListener {
            if (participant.isVideoEnabled) {
                participant.disableVideo()
            } else {
                participant.enableVideo()
            }
            notifyItemChanged(position, participant)
        }
        // Update microphone and camera UI icons according to Participant's Audio and Video track state
        viewHolder.connectionState.visibility = if (participant.isConnectionLost) View.VISIBLE else View.GONE
        viewHolder.layoutProgress.visibility = if (participant.isProgressReconnection) View.VISIBLE else View.GONE
        viewHolder.mic.setBackgroundResource(if (participant.isAudioEnabled) R.drawable.ic_mic_on else R.drawable.ic_mic_off)
        viewHolder.cam.setBackgroundResource(if (participant.isVideoEnabled) R.drawable.ic_video_on else R.drawable.ic_video_off)

        viewHolder.name.text = participant.name
}
```

{% endtab %}
{% endtabs %}

## Switching camera <a href="#android-javaandkotlin-switchingcamera" id="android-javaandkotlin-switchingcamera"></a>

During streaming, you can switch from front to back camera by a simple call to the Session’s function `switchCamera`

## Running the application <a href="#android-javaandkotlin-runningtheapplication" id="android-javaandkotlin-runningtheapplication"></a>

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

* [Java sample application](https://bitbucket.org/svmt/samplewatchtogether-java-2.0/src/master/)
* [Kotlin sample application](https://bitbucket.org/svmt/samplewatchtogether-kotlin-2.0/src/master/)

## Release notes <a href="#android-javaandkotlin-releasenotes" id="android-javaandkotlin-releasenotes"></a>

* The Android SDK’s support Android 6.0 version and higher

## Next steps <a href="#android-javaandkotlin-nextsteps" id="android-javaandkotlin-nextsteps"></a>

* Learn more about Watch Together architecture - [Watch Together overview](http://svmtse.atlassian.net/wiki/spaces/SC/pages/80052361/Watch+Together+overview)
* To understand better how to set up the Authentication please have a look at the [Authentication overview](https://documentation.sceenic.co/watch-together-sdk/sscale-confluence-overview).

## Support <a href="#android-javaandkotlin-support" id="android-javaandkotlin-support"></a>

Need technical support? contact us at <Support@sceenic.co>.
