From 0cf9aaf9cf2c3e37123bfd4d4ba3ea21eb98dd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Fri, 27 Sep 2024 12:51:29 +0200 Subject: [PATCH 1/2] Add User-Agent with the App Data --- .../core/internal/module/ConnectionModule.kt | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt index d7ee523639..2b5b85b0e5 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt @@ -18,6 +18,7 @@ package io.getstream.video.android.core.internal.module import android.content.Context import android.net.ConnectivityManager +import android.os.Build import io.getstream.video.android.core.StreamVideo import io.getstream.video.android.core.api.SignalServerService import io.getstream.video.android.core.dispatchers.DispatcherProvider @@ -67,7 +68,7 @@ internal class ConnectionModule( private val authInterceptor: CoordinatorAuthInterceptor by lazy { CoordinatorAuthInterceptor(apiKey, userToken) } - private val headersInterceptor: HeadersInterceptor by lazy { HeadersInterceptor() } + private val headersInterceptor: HeadersInterceptor by lazy { HeadersInterceptor(context) } val okHttpClient: OkHttpClient by lazy { buildOkHttpClient() } val networkStateProvider: NetworkStateProvider by lazy { NetworkStateProvider( @@ -288,12 +289,57 @@ internal class CoordinatorAuthInterceptor( } } -internal class HeadersInterceptor : Interceptor { +internal class HeadersInterceptor( + context: Context, +) : Interceptor { + private val userAgent by lazy { buildUserAgent(context) } + override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() .newBuilder() + .addHeader("User-Agent", userAgent) .addHeader("X-Stream-Client", StreamVideo.buildSdkTrackingHeaders()) .build() return chain.proceed(request) } + + private fun buildUserAgent(context: Context): String { + with(context.packageManager) { + val versionName = runCatching { + getPackageInfo(context.packageName, 0).versionName + }.getOrNull() ?: "nameNotFound" + val versionCode = runCatching { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + getPackageInfo(context.packageName, 0).longVersionCode.toString() + } else { + getPackageInfo(context.packageName, 0).versionCode.toString() + } + }.getOrNull() ?: "versionCodeNotFound" + + val applicationInfo = context.applicationInfo + val stringId = applicationInfo.labelRes + val appName = + if (stringId == 0) { + applicationInfo.nonLocalizedLabel.toString() + } else { + context.getString(stringId) + } + + val manufacturer = Build.MANUFACTURER + val model = Build.MODEL + val version = Build.VERSION.SDK_INT + val versionRelease = Build.VERSION.RELEASE + + val installerName = runCatching { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + getInstallSourceInfo(context.packageName).installingPackageName + } else { + getInstallerPackageName(context.packageName) + } + }.getOrNull() ?: "StandAloneInstall" + + return "$appName / $versionName($versionCode); $installerName; ($manufacturer; " + + "$model; SDK $version; Android $versionRelease)" + } + } } From 94242b45b7916382e09ca4b2d1fb79be05fdae0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Tue, 15 Oct 2024 14:31:09 +0200 Subject: [PATCH 2/2] Sanitize User Agen Header --- .../core/internal/module/ConnectionModule.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt index 2b5b85b0e5..f2a27b0129 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/internal/module/ConnectionModule.kt @@ -41,6 +41,7 @@ import retrofit2.converter.moshi.MoshiConverterFactory import retrofit2.converter.scalars.ScalarsConverterFactory import retrofit2.converter.wire.WireConverterFactory import java.io.IOException +import java.text.Normalizer import java.util.concurrent.TimeUnit /** @@ -338,8 +339,16 @@ internal class HeadersInterceptor( } }.getOrNull() ?: "StandAloneInstall" - return "$appName / $versionName($versionCode); $installerName; ($manufacturer; " + - "$model; SDK $version; Android $versionRelease)" + return ( + "$appName / $versionName($versionCode); $installerName; ($manufacturer; " + + "$model; SDK $version; Android $versionRelease)" + ) + .sanitize() } } + + private fun String.sanitize(): String { + return Normalizer.normalize(this, Normalizer.Form.NFD) + .replace("[^\\p{ASCII}]".toRegex(), "") + } }