From 65dc1e81261e003eb48efa18ed9f9b53234b29be Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Thu, 27 Nov 2025 16:39:04 +0100 Subject: [PATCH 1/5] Add default parameters for the creation method --- app/src/main/AndroidManifest.xml | 1 + .../android/core/sample/SampleActivity.kt | 61 +++---- .../android/core/sample/SampleApp.kt | 76 +++++++++ .../core/sample/client/StreamClient.kt | 158 ------------------ .../android/core/api/StreamClient.kt | 91 +++++++--- 5 files changed, 168 insertions(+), 219 deletions(-) create mode 100644 app/src/main/java/io/getstream/android/core/sample/SampleApp.kt delete mode 100644 app/src/main/java/io/getstream/android/core/sample/client/StreamClient.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d45c38e..6f3909a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,7 @@ xmlns:tools="http://schemas.android.com/tools"> Column( modifier = - Modifier.fillMaxSize() + Modifier + .fillMaxSize() .padding(innerPadding) .verticalScroll(scrollState) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp), ) { Greeting(name = "Android") - ClientInfo(streamClient = streamClient2) - val state = streamClient?.connectionState?.collectAsStateWithLifecycle() + ClientInfo(streamClient = streamClient) + val state = streamClient.connectionState?.collectAsStateWithLifecycle() val buttonState = when (state?.value) { is StreamConnectionState.Connected -> { @@ -145,7 +118,7 @@ class SampleActivity : ComponentActivity(), StreamClientListener { "Disconnect", true, { - lifecycleScope.launch { streamClient?.disconnect() } + lifecycleScope.launch { streamClient.disconnect() } Unit }, ) @@ -174,8 +147,14 @@ class SampleActivity : ComponentActivity(), StreamClientListener { } } } + + override fun onDestroy() { + super.onDestroy() + handle?.cancel() + } } + @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text(text = "Hello $name!", modifier = modifier) diff --git a/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt new file mode 100644 index 0000000..b3701da --- /dev/null +++ b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt @@ -0,0 +1,76 @@ +package io.getstream.android.core.sample + +import android.annotation.SuppressLint +import android.app.Application +import android.os.Build +import androidx.lifecycle.lifecycleScope +import io.getstream.android.core.api.StreamClient +import io.getstream.android.core.api.authentication.StreamTokenProvider +import io.getstream.android.core.api.model.config.StreamClientSerializationConfig +import io.getstream.android.core.api.model.value.StreamApiKey +import io.getstream.android.core.api.model.value.StreamHttpClientInfoHeader +import io.getstream.android.core.api.model.value.StreamToken +import io.getstream.android.core.api.model.value.StreamUserId +import io.getstream.android.core.api.model.value.StreamWsUrl +import io.getstream.android.core.api.serialization.StreamEventSerialization +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlin.coroutines.coroutineContext + +class SampleApp : Application() { + + lateinit var streamClient: StreamClient + private val userId = StreamUserId.fromString("sample-user") + private val token = StreamToken.fromString( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicGV0YXIifQ.mZFi4iSblaIoyo9JDdcxIkGkwI-tuApeSBawxpz42rs" + ) + private val coroutinesScope = CoroutineScope(SupervisorJob() + Dispatchers.IO + Dispatchers.Main + Dispatchers.Default) + + companion object { + lateinit var instance: SampleApp + } + + @SuppressLint("NotKeepingInstance") + override fun onCreate() { + super.onCreate() + instance = this + streamClient = StreamClient( + context = this.applicationContext, + scope = coroutinesScope, + apiKey = StreamApiKey.fromString("pd67s34fzpgw"), + userId = userId, + products = listOf("feeds", "chat", "video"), + wsUrl = + StreamWsUrl.fromString( + "wss://chat-edge-frankfurt-ce1.stream-io-api.com/api/v2/connect" + ), + clientInfoHeader = + StreamHttpClientInfoHeader.create( + product = "android-core", + productVersion = "1.1.0", + os = "Android", + apiLevel = Build.VERSION.SDK_INT, + deviceModel = "Pixel 7 Pro", + app = "Stream Android Core Sample", + appVersion = "1.0.0", + ), + tokenProvider = + object : StreamTokenProvider { + override suspend fun loadToken(userId: StreamUserId): StreamToken { + return token + } + }, + serializationConfig = + StreamClientSerializationConfig.default( + object : StreamEventSerialization { + override fun serialize(data: Unit): Result = Result.success("") + + override fun deserialize(raw: String): Result = + Result.success(Unit) + } + ), + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/getstream/android/core/sample/client/StreamClient.kt b/app/src/main/java/io/getstream/android/core/sample/client/StreamClient.kt deleted file mode 100644 index bd4941f..0000000 --- a/app/src/main/java/io/getstream/android/core/sample/client/StreamClient.kt +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. - * - * Licensed under the Stream License; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/GetStream/stream-core-android/blob/main/LICENSE - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.getstream.android.core.sample.client - -import android.content.Context -import io.getstream.android.core.api.StreamClient -import io.getstream.android.core.api.authentication.StreamTokenManager -import io.getstream.android.core.api.authentication.StreamTokenProvider -import io.getstream.android.core.api.components.StreamAndroidComponentsProvider -import io.getstream.android.core.api.log.StreamLogger -import io.getstream.android.core.api.log.StreamLoggerProvider -import io.getstream.android.core.api.model.config.StreamClientSerializationConfig -import io.getstream.android.core.api.model.value.StreamApiKey -import io.getstream.android.core.api.model.value.StreamHttpClientInfoHeader -import io.getstream.android.core.api.model.value.StreamUserId -import io.getstream.android.core.api.model.value.StreamWsUrl -import io.getstream.android.core.api.observers.lifecycle.StreamLifecycleMonitor -import io.getstream.android.core.api.observers.network.StreamNetworkMonitor -import io.getstream.android.core.api.processing.StreamBatcher -import io.getstream.android.core.api.processing.StreamRetryProcessor -import io.getstream.android.core.api.processing.StreamSerialProcessingQueue -import io.getstream.android.core.api.processing.StreamSingleFlightProcessor -import io.getstream.android.core.api.recovery.StreamConnectionRecoveryEvaluator -import io.getstream.android.core.api.serialization.StreamEventSerialization -import io.getstream.android.core.api.socket.StreamConnectionIdHolder -import io.getstream.android.core.api.socket.StreamWebSocketFactory -import io.getstream.android.core.api.socket.listeners.StreamClientListener -import io.getstream.android.core.api.socket.monitor.StreamHealthMonitor -import io.getstream.android.core.api.subscribe.StreamSubscriptionManager -import kotlinx.coroutines.CoroutineScope - -/** - * Creates a [createStreamClient] instance with the given configuration and dependencies. - * - * @param scope The coroutine scope. - * @param apiKey The API key. - * @param userId The user ID. - * @param wsUrl The WebSocket URL. - * @param clientInfoHeader The client info header. - * @param tokenProvider The token provider. - * @return A new [createStreamClient] instance. - */ -fun createStreamClient( - context: Context, - scope: CoroutineScope, - apiKey: StreamApiKey, - userId: StreamUserId, - wsUrl: StreamWsUrl, - clientInfoHeader: StreamHttpClientInfoHeader, - tokenProvider: StreamTokenProvider, -): StreamClient { - val logProvider = - StreamLoggerProvider.Companion.defaultAndroidLogger( - minLevel = StreamLogger.LogLevel.Verbose, - honorAndroidIsLoggable = false, - ) - val clientSubscriptionManager = - StreamSubscriptionManager( - logger = logProvider.taggedLogger("SCClientSubscriptions"), - maxStrongSubscriptions = 250, - maxWeakSubscriptions = 250, - ) - val singleFlight = StreamSingleFlightProcessor(scope) - val tokenManager = StreamTokenManager(userId, tokenProvider, singleFlight) - val serialQueue = - StreamSerialProcessingQueue( - logger = logProvider.taggedLogger("SCSerialProcessing"), - scope = scope, - ) - val retryProcessor = StreamRetryProcessor(logger = logProvider.taggedLogger("SCRetryProcessor")) - val connectionIdHolder = StreamConnectionIdHolder() - val socketFactory = - StreamWebSocketFactory(logger = logProvider.taggedLogger("SCWebSocketFactory")) - val healthMonitor = - StreamHealthMonitor(logger = logProvider.taggedLogger("SCHealthMonitor"), scope = scope) - val batcher = - StreamBatcher( - scope = scope, - batchSize = 10, - initialDelayMs = 100L, - maxDelayMs = 1_000L, - ) - - val androidComponentsProvider = StreamAndroidComponentsProvider(context) - val connectivityManager = androidComponentsProvider.connectivityManager().getOrThrow() - val wifiManager = androidComponentsProvider.wifiManager().getOrThrow() - val telephonyManager = androidComponentsProvider.telephonyManager().getOrThrow() - val networkMonitor = - StreamNetworkMonitor( - logger = logProvider.taggedLogger("SCNetworkMonitor"), - scope = scope, - connectivityManager = connectivityManager, - wifiManager = wifiManager, - telephonyManager = telephonyManager, - subscriptionManager = - StreamSubscriptionManager( - logger = logProvider.taggedLogger("SCNetworkMonitorSubscriptions") - ), - ) - val lifecycleMonitor = - StreamLifecycleMonitor( - logger = logProvider.taggedLogger("SCLifecycleMonitor"), - subscriptionManager = - StreamSubscriptionManager( - logger = logProvider.taggedLogger("SCLifecycleMonitorSubscriptions") - ), - lifecycle = androidComponentsProvider.lifecycle(), - ) - - return StreamClient( - scope = scope, - apiKey = apiKey, - userId = userId, - wsUrl = wsUrl, - products = listOf("feeds"), - clientInfoHeader = clientInfoHeader, - tokenProvider = tokenProvider, - logProvider = logProvider, - clientSubscriptionManager = clientSubscriptionManager, - tokenManager = tokenManager, - singleFlight = singleFlight, - serialQueue = serialQueue, - retryProcessor = retryProcessor, - connectionIdHolder = connectionIdHolder, - socketFactory = socketFactory, - healthMonitor = healthMonitor, - networkMonitor = networkMonitor, - serializationConfig = - StreamClientSerializationConfig.default( - object : StreamEventSerialization { - override fun serialize(data: Unit): Result = Result.success("") - - override fun deserialize(raw: String): Result = Result.success(Unit) - } - ), - lifecycleMonitor = lifecycleMonitor, - connectionRecoveryEvaluator = - StreamConnectionRecoveryEvaluator( - logger = logProvider.taggedLogger("SCConnectionRecoveryEvaluator"), - singleFlightProcessor = singleFlight, - ), - batcher = batcher, - ) -} diff --git a/stream-android-core/src/main/java/io/getstream/android/core/api/StreamClient.kt b/stream-android-core/src/main/java/io/getstream/android/core/api/StreamClient.kt index f67201f..2fa1e24 100644 --- a/stream-android-core/src/main/java/io/getstream/android/core/api/StreamClient.kt +++ b/stream-android-core/src/main/java/io/getstream/android/core/api/StreamClient.kt @@ -17,9 +17,11 @@ package io.getstream.android.core.api import android.annotation.SuppressLint +import android.content.Context import io.getstream.android.core.annotations.StreamInternalApi import io.getstream.android.core.api.authentication.StreamTokenManager import io.getstream.android.core.api.authentication.StreamTokenProvider +import io.getstream.android.core.api.components.StreamAndroidComponentsProvider import io.getstream.android.core.api.http.StreamOkHttpInterceptors import io.getstream.android.core.api.log.StreamLoggerProvider import io.getstream.android.core.api.model.config.StreamClientSerializationConfig @@ -206,36 +208,85 @@ public interface StreamClient : StreamObservable { @SuppressLint("ExposeAsStateFlow") @StreamInternalApi public fun StreamClient( + + // Android + scope: CoroutineScope, + context: Context, + // Client config apiKey: StreamApiKey, userId: StreamUserId, wsUrl: StreamWsUrl, products: List, clientInfoHeader: StreamHttpClientInfoHeader, - clientSubscriptionManager: StreamSubscriptionManager, - // Token tokenProvider: StreamTokenProvider, - tokenManager: StreamTokenManager, - // Processing - singleFlight: StreamSingleFlightProcessor, - serialQueue: StreamSerialProcessingQueue, - retryProcessor: StreamRetryProcessor, - scope: CoroutineScope, - // Socket - connectionIdHolder: StreamConnectionIdHolder, - socketFactory: StreamWebSocketFactory, - batcher: StreamBatcher, - // Monitoring - healthMonitor: StreamHealthMonitor, - networkMonitor: StreamNetworkMonitor, - lifecycleMonitor: StreamLifecycleMonitor, - connectionRecoveryEvaluator: StreamConnectionRecoveryEvaluator, - // Http - httpConfig: StreamHttpConfig? = null, - // Serialization serializationConfig: StreamClientSerializationConfig, + httpConfig: StreamHttpConfig? = null, + + // Component provider + androidComponentsProvider: StreamAndroidComponentsProvider = + StreamAndroidComponentsProvider(context.applicationContext), + // Logging logProvider: StreamLoggerProvider = StreamLoggerProvider.defaultAndroidLogger(), + + // Subscriptions + clientSubscriptionManager: StreamSubscriptionManager = + StreamSubscriptionManager( + logger = logProvider.taggedLogger("SCClientSubscriptions"), + maxStrongSubscriptions = 250, + maxWeakSubscriptions = 250, + ), + + // Processing + singleFlight: StreamSingleFlightProcessor = StreamSingleFlightProcessor(scope), + serialQueue: StreamSerialProcessingQueue = + StreamSerialProcessingQueue( + logger = logProvider.taggedLogger("SCSerialProcessing"), + scope = scope, + ), + retryProcessor: StreamRetryProcessor = + StreamRetryProcessor(logger = logProvider.taggedLogger("SCRetryProcessor")), + + // Token + tokenManager: StreamTokenManager = StreamTokenManager(userId, tokenProvider, singleFlight), + + // Socket + connectionIdHolder: StreamConnectionIdHolder = StreamConnectionIdHolder(), + socketFactory: StreamWebSocketFactory = + StreamWebSocketFactory(logger = logProvider.taggedLogger("SCWebSocketFactory")), + batcher: StreamBatcher = + StreamBatcher(scope = scope, batchSize = 10, initialDelayMs = 100L, maxDelayMs = 1_000L), + + // Monitoring + healthMonitor: StreamHealthMonitor = + StreamHealthMonitor(logger = logProvider.taggedLogger("SCHealthMonitor"), scope = scope), + networkMonitor: StreamNetworkMonitor = + StreamNetworkMonitor( + logger = logProvider.taggedLogger("SCNetworkMonitor"), + scope = scope, + connectivityManager = androidComponentsProvider.connectivityManager().getOrThrow(), + wifiManager = androidComponentsProvider.wifiManager().getOrThrow(), + telephonyManager = androidComponentsProvider.telephonyManager().getOrThrow(), + subscriptionManager = + StreamSubscriptionManager( + logger = logProvider.taggedLogger("SCNetworkMonitorSubscriptions") + ), + ), + lifecycleMonitor: StreamLifecycleMonitor = + StreamLifecycleMonitor( + logger = logProvider.taggedLogger("SCLifecycleMonitor"), + subscriptionManager = + StreamSubscriptionManager( + logger = logProvider.taggedLogger("SCLifecycleMonitorSubscriptions") + ), + lifecycle = androidComponentsProvider.lifecycle(), + ), + connectionRecoveryEvaluator: StreamConnectionRecoveryEvaluator = + StreamConnectionRecoveryEvaluator( + logger = logProvider.taggedLogger("SCConnectionRecoveryEvaluator"), + singleFlightProcessor = singleFlight, + ), ): StreamClient { val clientLogger = logProvider.taggedLogger(tag = "SCClient") val parent = scope.coroutineContext[Job] From 4808568546ab8aee0bb9248a345d960c18be50f1 Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Thu, 27 Nov 2025 16:52:18 +0100 Subject: [PATCH 2/5] Update tests --- .../io/getstream/android/core/api/StreamClientFactoryTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/stream-android-core/src/test/java/io/getstream/android/core/api/StreamClientFactoryTest.kt b/stream-android-core/src/test/java/io/getstream/android/core/api/StreamClientFactoryTest.kt index 47002dc..231f713 100644 --- a/stream-android-core/src/test/java/io/getstream/android/core/api/StreamClientFactoryTest.kt +++ b/stream-android-core/src/test/java/io/getstream/android/core/api/StreamClientFactoryTest.kt @@ -141,6 +141,7 @@ internal class StreamClientFactoryTest { val client = StreamClient( + context = mockk(relaxed = true), apiKey = deps.apiKey, userId = deps.userId, wsUrl = deps.wsUrl, From b4bd23b735b621d0348f7dd7cb4319200b94e982 Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Thu, 27 Nov 2025 17:02:45 +0100 Subject: [PATCH 3/5] Spotless --- .../android/core/sample/SampleActivity.kt | 13 +-- .../android/core/sample/SampleApp.kt | 102 ++++++++++-------- 2 files changed, 60 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt b/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt index dd466e9..13315e2 100644 --- a/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt +++ b/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt @@ -16,7 +16,6 @@ package io.getstream.android.core.sample -import android.os.Build import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -40,16 +39,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import io.getstream.android.core.api.StreamClient -import io.getstream.android.core.api.authentication.StreamTokenProvider -import io.getstream.android.core.api.model.config.StreamClientSerializationConfig import io.getstream.android.core.api.model.connection.StreamConnectionState import io.getstream.android.core.api.model.connection.recovery.Recovery -import io.getstream.android.core.api.model.value.StreamApiKey -import io.getstream.android.core.api.model.value.StreamHttpClientInfoHeader -import io.getstream.android.core.api.model.value.StreamToken -import io.getstream.android.core.api.model.value.StreamUserId -import io.getstream.android.core.api.model.value.StreamWsUrl -import io.getstream.android.core.api.serialization.StreamEventSerialization import io.getstream.android.core.api.socket.listeners.StreamClientListener import io.getstream.android.core.api.subscribe.StreamSubscription import io.getstream.android.core.api.subscribe.StreamSubscriptionManager @@ -101,8 +92,7 @@ class SampleActivity : ComponentActivity(), StreamClientListener { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Column( modifier = - Modifier - .fillMaxSize() + Modifier.fillMaxSize() .padding(innerPadding) .verticalScroll(scrollState) .padding(16.dp), @@ -154,7 +144,6 @@ class SampleActivity : ComponentActivity(), StreamClientListener { } } - @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text(text = "Hello $name!", modifier = modifier) diff --git a/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt index b3701da..14e0417 100644 --- a/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt +++ b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt @@ -1,9 +1,24 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-core-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.getstream.android.core.sample import android.annotation.SuppressLint import android.app.Application import android.os.Build -import androidx.lifecycle.lifecycleScope import io.getstream.android.core.api.StreamClient import io.getstream.android.core.api.authentication.StreamTokenProvider import io.getstream.android.core.api.model.config.StreamClientSerializationConfig @@ -16,16 +31,17 @@ import io.getstream.android.core.api.serialization.StreamEventSerialization import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import kotlin.coroutines.coroutineContext class SampleApp : Application() { lateinit var streamClient: StreamClient private val userId = StreamUserId.fromString("sample-user") - private val token = StreamToken.fromString( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicGV0YXIifQ.mZFi4iSblaIoyo9JDdcxIkGkwI-tuApeSBawxpz42rs" - ) - private val coroutinesScope = CoroutineScope(SupervisorJob() + Dispatchers.IO + Dispatchers.Main + Dispatchers.Default) + private val token = + StreamToken.fromString( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicGV0YXIifQ.mZFi4iSblaIoyo9JDdcxIkGkwI-tuApeSBawxpz42rs" + ) + private val coroutinesScope = + CoroutineScope(SupervisorJob() + Dispatchers.IO + Dispatchers.Main + Dispatchers.Default) companion object { lateinit var instance: SampleApp @@ -35,42 +51,42 @@ class SampleApp : Application() { override fun onCreate() { super.onCreate() instance = this - streamClient = StreamClient( - context = this.applicationContext, - scope = coroutinesScope, - apiKey = StreamApiKey.fromString("pd67s34fzpgw"), - userId = userId, - products = listOf("feeds", "chat", "video"), - wsUrl = - StreamWsUrl.fromString( - "wss://chat-edge-frankfurt-ce1.stream-io-api.com/api/v2/connect" - ), - clientInfoHeader = - StreamHttpClientInfoHeader.create( - product = "android-core", - productVersion = "1.1.0", - os = "Android", - apiLevel = Build.VERSION.SDK_INT, - deviceModel = "Pixel 7 Pro", - app = "Stream Android Core Sample", - appVersion = "1.0.0", - ), - tokenProvider = - object : StreamTokenProvider { - override suspend fun loadToken(userId: StreamUserId): StreamToken { - return token - } - }, - serializationConfig = - StreamClientSerializationConfig.default( - object : StreamEventSerialization { - override fun serialize(data: Unit): Result = Result.success("") + streamClient = + StreamClient( + context = this.applicationContext, + scope = coroutinesScope, + apiKey = StreamApiKey.fromString("pd67s34fzpgw"), + userId = userId, + products = listOf("feeds", "chat", "video"), + wsUrl = + StreamWsUrl.fromString( + "wss://chat-edge-frankfurt-ce1.stream-io-api.com/api/v2/connect" + ), + clientInfoHeader = + StreamHttpClientInfoHeader.create( + product = "android-core", + productVersion = "1.1.0", + os = "Android", + apiLevel = Build.VERSION.SDK_INT, + deviceModel = "Pixel 7 Pro", + app = "Stream Android Core Sample", + appVersion = "1.0.0", + ), + tokenProvider = + object : StreamTokenProvider { + override suspend fun loadToken(userId: StreamUserId): StreamToken { + return token + } + }, + serializationConfig = + StreamClientSerializationConfig.default( + object : StreamEventSerialization { + override fun serialize(data: Unit): Result = Result.success("") - override fun deserialize(raw: String): Result = - Result.success(Unit) - } - ), - ) + override fun deserialize(raw: String): Result = + Result.success(Unit) + } + ), + ) } - -} \ No newline at end of file +} From 742986ef2b7736ac999959c187bbcec793486023 Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Thu, 27 Nov 2025 17:03:23 +0100 Subject: [PATCH 4/5] Remove delay --- .../java/io/getstream/android/core/sample/SampleActivity.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt b/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt index 13315e2..ba5e45a 100644 --- a/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt +++ b/app/src/main/java/io/getstream/android/core/sample/SampleActivity.kt @@ -46,7 +46,6 @@ import io.getstream.android.core.api.subscribe.StreamSubscription import io.getstream.android.core.api.subscribe.StreamSubscriptionManager import io.getstream.android.core.sample.ui.ConnectionStateCard import io.getstream.android.core.sample.ui.theme.StreamandroidcoreTheme -import kotlinx.coroutines.delay import kotlinx.coroutines.launch class SampleActivity : ComponentActivity(), StreamClientListener { @@ -67,10 +66,7 @@ class SampleActivity : ComponentActivity(), StreamClientListener { super.onCreate(savedInstanceState) val streamClient = SampleApp.instance.streamClient lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { - delay(5000) - streamClient.connect() - } + repeatOnLifecycle(Lifecycle.State.CREATED) { streamClient.connect() } } if (handle == null) { handle = From e1b74c1c4e1dd027b6f0a3eb317e8f577d566a79 Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Thu, 27 Nov 2025 17:04:56 +0100 Subject: [PATCH 5/5] Remove redundant dispatchers --- .../main/java/io/getstream/android/core/sample/SampleApp.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt index 14e0417..a8e8488 100644 --- a/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt +++ b/app/src/main/java/io/getstream/android/core/sample/SampleApp.kt @@ -40,8 +40,7 @@ class SampleApp : Application() { StreamToken.fromString( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicGV0YXIifQ.mZFi4iSblaIoyo9JDdcxIkGkwI-tuApeSBawxpz42rs" ) - private val coroutinesScope = - CoroutineScope(SupervisorJob() + Dispatchers.IO + Dispatchers.Main + Dispatchers.Default) + private val coroutinesScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) companion object { lateinit var instance: SampleApp