davidliu
Committed by GitHub

Send client info on connect (#48)

* Fix tests

* Fix github actions

* send client info
1 package io.livekit.android.room 1 package io.livekit.android.room
2 2
  3 +import android.net.Uri
3 import com.google.protobuf.util.JsonFormat 4 import com.google.protobuf.util.JsonFormat
4 import com.vdurmont.semver4j.Semver 5 import com.vdurmont.semver4j.Semver
5 import io.livekit.android.ConnectOptions 6 import io.livekit.android.ConnectOptions
@@ -7,6 +8,7 @@ import io.livekit.android.Version @@ -7,6 +8,7 @@ import io.livekit.android.Version
7 import io.livekit.android.dagger.InjectionNames 8 import io.livekit.android.dagger.InjectionNames
8 import io.livekit.android.room.participant.ParticipantTrackPermission 9 import io.livekit.android.room.participant.ParticipantTrackPermission
9 import io.livekit.android.room.track.Track 10 import io.livekit.android.room.track.Track
  11 +import io.livekit.android.stats.getClientInfo
10 import io.livekit.android.util.CloseableCoroutineScope 12 import io.livekit.android.util.CloseableCoroutineScope
11 import io.livekit.android.util.Either 13 import io.livekit.android.util.Either
12 import io.livekit.android.util.LKLog 14 import io.livekit.android.util.LKLog
@@ -89,22 +91,8 @@ constructor( @@ -89,22 +91,8 @@ constructor(
89 token: String, 91 token: String,
90 options: ConnectOptions 92 options: ConnectOptions
91 ): Either<LivekitRtc.JoinResponse, Unit> { 93 ): Either<LivekitRtc.JoinResponse, Unit> {
92 - var wsUrlString = "$url/rtc" +  
93 - "?protocol=$PROTOCOL_VERSION" +  
94 - "&$CONNECT_QUERY_TOKEN=$token" +  
95 - "&sdk=$SDK_TYPE" +  
96 - "&version=${Version.CLIENT_VERSION}"  
97 - isReconnecting = false  
98 - wsUrlString += "&auto_subscribe="  
99 - wsUrlString += if (options.autoSubscribe) {  
100 - "1"  
101 - } else {  
102 - "0"  
103 - }  
104 - if (options.reconnect) {  
105 - wsUrlString += "&reconnect=1"  
106 - isReconnecting = true  
107 - } 94 + val wsUrlString = "$url/rtc" + createConnectionParams(token, getClientInfo(), options)
  95 + isReconnecting = options.reconnect
108 96
109 LKLog.i { "connecting to $wsUrlString" } 97 LKLog.i { "connecting to $wsUrlString" }
110 98
@@ -125,6 +113,36 @@ constructor( @@ -125,6 +113,36 @@ constructor(
125 } 113 }
126 } 114 }
127 115
  116 + private fun createConnectionParams(
  117 + token: String,
  118 + clientInfo: LivekitModels.ClientInfo,
  119 + options: ConnectOptions
  120 + ): String {
  121 +
  122 + val queryParams = mutableListOf<Pair<String, String>>()
  123 + queryParams.add(CONNECT_QUERY_TOKEN to token)
  124 +
  125 + if (options.reconnect) {
  126 + queryParams.add(CONNECT_QUERY_RECONNECT to 1.toString())
  127 + }
  128 +
  129 + val autoSubscribe = if(options.autoSubscribe) 1 else 0
  130 + queryParams.add(CONNECT_QUERY_AUTOSUBSCRIBE to autoSubscribe.toString())
  131 +
  132 + // Client info
  133 + queryParams.add(CONNECT_QUERY_SDK to "android")
  134 + queryParams.add(CONNECT_QUERY_VERSION to clientInfo.version)
  135 + queryParams.add(CONNECT_QUERY_PROTOCOL to clientInfo.protocol.toString())
  136 + queryParams.add(CONNECT_QUERY_DEVICE_MODEL to clientInfo.deviceModel)
  137 + queryParams.add(CONNECT_QUERY_OS to clientInfo.os)
  138 + queryParams.add(CONNECT_QUERY_OS_VERSION to clientInfo.osVersion)
  139 +
  140 + return queryParams.foldIndexed("") { index, acc, pair ->
  141 + val separator = if(index == 0) "?" else "&"
  142 + acc + separator + "${pair.first}=${pair.second}"
  143 + }
  144 + }
  145 +
128 /** 146 /**
129 * Notifies that the downstream consumers of SignalClient are ready to consume messages. 147 * Notifies that the downstream consumers of SignalClient are ready to consume messages.
130 * Until this method is called, any messages received through the websocket are buffered. 148 * Until this method is called, any messages received through the websocket are buffered.
@@ -495,7 +513,7 @@ constructor( @@ -495,7 +513,7 @@ constructor(
495 */ 513 */
496 fun close(code: Int = 1000, reason: String = "Normal Closure") { 514 fun close(code: Int = 1000, reason: String = "Normal Closure") {
497 isConnected = false 515 isConnected = false
498 - if(::coroutineScope.isInitialized) { 516 + if (::coroutineScope.isInitialized) {
499 coroutineScope.close() 517 coroutineScope.close()
500 } 518 }
501 currentWs?.close(code, reason) 519 currentWs?.close(code, reason)
@@ -525,6 +543,14 @@ constructor( @@ -525,6 +543,14 @@ constructor(
525 543
526 companion object { 544 companion object {
527 const val CONNECT_QUERY_TOKEN = "access_token" 545 const val CONNECT_QUERY_TOKEN = "access_token"
  546 + const val CONNECT_QUERY_RECONNECT = "reconnect"
  547 + const val CONNECT_QUERY_AUTOSUBSCRIBE = "autoSubscribe"
  548 + const val CONNECT_QUERY_SDK = "sdk"
  549 + const val CONNECT_QUERY_VERSION = "version"
  550 + const val CONNECT_QUERY_PROTOCOL = "protocol"
  551 + const val CONNECT_QUERY_DEVICE_MODEL = "device_model"
  552 + const val CONNECT_QUERY_OS = "os"
  553 + const val CONNECT_QUERY_OS_VERSION = "os_version"
528 554
529 const val SD_TYPE_ANSWER = "answer" 555 const val SD_TYPE_ANSWER = "answer"
530 const val SD_TYPE_OFFER = "offer" 556 const val SD_TYPE_OFFER = "offer"
  1 +package io.livekit.android.stats
  2 +
  3 +import android.os.Build
  4 +import io.livekit.android.BuildConfig
  5 +import io.livekit.android.room.SignalClient
  6 +import livekit.LivekitModels
  7 +
  8 +internal fun getClientInfo() = with(LivekitModels.ClientInfo.newBuilder()) {
  9 + sdk = LivekitModels.ClientInfo.SDK.ANDROID
  10 + protocol = SignalClient.PROTOCOL_VERSION
  11 + version = BuildConfig.VERSION_NAME
  12 + os = "android"
  13 + osVersion = Build.VERSION.RELEASE ?: ""
  14 +
  15 + val vendor = Build.MANUFACTURER ?: ""
  16 + val model = Build.MODEL ?: ""
  17 + deviceModel = ("$vendor $model").trim()
  18 + build()
  19 +}