David Zhao

Support setting autosubscribe to false, refactored ConnectOptions

<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
<bytecodeTargetLevel target="12" />
</component>
</project>
\ No newline at end of file
... ...
... ... @@ -11,7 +11,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.0-alpha15'
classpath 'com.android.tools.build:gradle:7.0.0-beta02'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
... ...
... ... @@ -15,8 +15,6 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName VERSION_NAME
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
... ...
package io.livekit.android
data class ConnectOptions(
val placeholder: Unit = Unit
)
\ No newline at end of file
class ConnectOptions(
var autoSubscribe: Boolean = true
) {
internal var reconnect: Boolean = false
}
... ...
... ... @@ -16,7 +16,7 @@ class LiveKit {
appContext: Context,
url: String,
token: String,
options: ConnectOptions,
options: ConnectOptions?,
listener: RoomListener?
): Room {
val ctx = appContext.applicationContext
... ... @@ -25,9 +25,9 @@ class LiveKit {
.create(ctx)
val room = component.roomFactory()
.create(options, ctx)
.create(ctx)
room.listener = listener
room.connect(url, token)
room.connect(url, token, options)
return room
}
... ...
package io.livekit.android.room
import com.github.ajalt.timberkt.Timber
import io.livekit.android.ConnectOptions
import io.livekit.android.dagger.InjectionNames
import io.livekit.android.room.track.TrackException
import io.livekit.android.room.util.*
... ... @@ -27,10 +28,10 @@ import kotlin.coroutines.suspendCoroutine
class RTCEngine
@Inject
constructor(
val client: RTCClient,
val client: SignalClient,
private val pctFactory: PeerConnectionTransport.Factory,
@Named(InjectionNames.DISPATCHER_IO) ioDispatcher: CoroutineDispatcher,
) : RTCClient.Listener, DataChannel.Observer {
) : SignalClient.Listener, DataChannel.Observer {
var listener: Listener? = null
internal var iceState: IceState = IceState.DISCONNECTED
set(value) {
... ... @@ -74,10 +75,10 @@ constructor(
client.listener = this
}
fun join(url: String, token: String) {
fun join(url: String, token: String, options: ConnectOptions?) {
sessionUrl = url
sessionToken = token
client.join(url, token)
client.join(url, token, options)
}
suspend fun addTrack(cid: String, name: String, kind: LivekitModels.TrackType): LivekitModels.TrackInfo {
... ... @@ -123,7 +124,9 @@ constructor(
coroutineScope.launch {
delay(startDelay)
if (iceState != IceState.DISCONNECTED && sessionUrl != null && sessionToken != null) {
client.join(sessionUrl!!, sessionToken!!, true)
val opts = ConnectOptions()
opts.reconnect = true
client.join(sessionUrl!!, sessionToken!!, opts)
}
}
}
... ... @@ -208,7 +211,7 @@ constructor(
}
if (iceServers.isEmpty()) {
iceServers.addAll(RTCClient.DEFAULT_ICE_SERVERS)
iceServers.addAll(SignalClient.DEFAULT_ICE_SERVERS)
}
info.iceServersList.forEach {
Timber.e{ "username = \"${it.username}\""}
... ...
... ... @@ -26,7 +26,6 @@ import kotlin.coroutines.suspendCoroutine
class Room
@AssistedInject
constructor(
@Assisted private val connectOptions: ConnectOptions,
@Assisted private val context: Context,
private val engine: RTCEngine,
private val eglBase: EglBase,
... ... @@ -65,9 +64,9 @@ constructor(
private var hasLostConnectivity: Boolean = false
private var connectContinuation: Continuation<Unit>? = null
suspend fun connect(url: String, token: String) {
suspend fun connect(url: String, token: String, options: ConnectOptions?) {
state = State.CONNECTING
engine.join(url, token)
engine.join(url, token, options)
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
... ... @@ -180,7 +179,7 @@ constructor(
*/
@AssistedFactory
interface Factory {
fun create(connectOptions: ConnectOptions, context: Context): Room
fun create(context: Context): Room
}
//------------------------------------- NetworkCallback -------------------------------------//
... ...
... ... @@ -2,6 +2,7 @@ package io.livekit.android.room
import com.github.ajalt.timberkt.Timber
import com.google.protobuf.util.JsonFormat
import io.livekit.android.ConnectOptions
import io.livekit.android.dagger.InjectionNames
import io.livekit.android.util.safe
import kotlinx.serialization.decodeFromString
... ... @@ -25,7 +26,7 @@ import javax.inject.Named
* SignalClient to LiveKit WS servers
* @suppress
*/
class RTCClient
class SignalClient
@Inject
constructor(
private val websocketFactory: WebSocket.Factory,
... ... @@ -44,15 +45,25 @@ constructor(
fun join(
url: String,
token: String,
reconnect: Boolean = false
options: ConnectOptions?,
) {
var wsUrlString = "$url/rtc?protocol=$PROTOCOL_VERSION&access_token=$token"
if (reconnect) {
wsUrlString += "&reconnect=1"
isReconnecting = false
if (options != null) {
wsUrlString += "&auto_subscribe="
wsUrlString += if (options.autoSubscribe) {
"1"
} else {
"0"
}
if (options.reconnect) {
wsUrlString += "&reconnect=1"
isReconnecting = true
}
}
Timber.i { "connecting to $wsUrlString" }
isReconnecting = reconnect
isConnected = false
currentWs?.cancel()
... ...
package io.livekit.android.room.participant
import com.github.ajalt.timberkt.Timber
import io.livekit.android.room.RTCClient
import io.livekit.android.room.SignalClient
import io.livekit.android.room.track.*
import io.livekit.android.util.CloseableCoroutineScope
import kotlinx.coroutines.SupervisorJob
... ... @@ -13,14 +13,14 @@ import org.webrtc.MediaStreamTrack
import org.webrtc.VideoTrack
class RemoteParticipant(
val rtcClient: RTCClient,
val signalClient: SignalClient,
sid: String,
identity: String? = null,
) : Participant(sid, identity) {
/**
* @suppress
*/
constructor(rtcClient: RTCClient, info: LivekitModels.ParticipantInfo) : this(rtcClient, info.sid, info.identity) {
constructor(signalClient: SignalClient, info: LivekitModels.ParticipantInfo) : this(signalClient, info.sid, info.identity) {
updateFromInfo(info)
}
... ...
... ... @@ -44,7 +44,7 @@ class RemoteTrackPublication(
unsubscribed = !subscribed
val participant = this.participant.get() as? RemoteParticipant ?: return
participant.rtcClient.sendUpdateSubscription(sid, !unsubscribed, videoQuality)
participant.signalClient.sendUpdateSubscription(sid, !unsubscribed, videoQuality)
}
/**
... ... @@ -72,6 +72,6 @@ class RemoteTrackPublication(
private fun sendUpdateTrackSettings() {
val participant = this.participant.get() as? RemoteParticipant ?: return
participant.rtcClient.sendUpdateTrackSettings(sid, disabled, videoQuality)
participant.signalClient.sendUpdateTrackSettings(sid, disabled, videoQuality)
}
}
\ No newline at end of file
... ...
package io.livekit.android.room.participant
import io.livekit.android.room.RTCClient
import io.livekit.android.room.SignalClient
import livekit.LivekitModels
import org.junit.Assert.*
import org.junit.Before
... ... @@ -9,13 +9,13 @@ import org.mockito.Mockito
class RemoteParticipantTest {
lateinit var rtcClient: RTCClient
lateinit var signalClient: SignalClient
lateinit var participant: RemoteParticipant
@Before
fun setup() {
rtcClient = Mockito.mock(RTCClient::class.java)
participant = RemoteParticipant(rtcClient, "sid")
signalClient = Mockito.mock(SignalClient::class.java)
participant = RemoteParticipant(signalClient, "sid")
}
@Test
... ... @@ -24,7 +24,7 @@ class RemoteParticipantTest {
.addTracks(TRACK_INFO)
.build()
participant = RemoteParticipant(rtcClient, info)
participant = RemoteParticipant(signalClient, info)
assertEquals(1, participant.tracks.values.size)
assertNotNull(participant.getTrackPublication(TRACK_INFO.sid))
... ...