Skip to content

Conversation

@rahul-lohra
Copy link
Contributor

@rahul-lohra rahul-lohra commented Jan 5, 2026

Goal

To prevent the SDK from hitting API rate limits by changing the default connection behavior. Currently, the SDK automatically establishes a WebSocket connection upon initialization. This can lead to excessive, unnecessary connections for clients who initialize the SDK at startup but do not immediately use video features, causing them to hit rate limits.

Implementation

To fix this, this PR introduces a connectOnInit flag in the StreamVideoBuilder. By setting connectOnInit = false, developers can now defer the connection until it's explicitly required. The SDK will still automatically connect internally when a core action is performed (like starting a call), ensuring functionality remains seamless while giving developers the control to reduce unnecessary startup connections.

Example Usage

 StreamVideoBuilder(connectOnInit = false).build()
 
 //To manually connect to websocket
 StreamVideo.instanceOrNull()?.connect()

🎨 UI Changes

None

Testing

Just perform audio/video call and check if you see cooridnator socket events

Summary by CodeRabbit

  • New Features
    • Added connectOnInit parameter to control automatic WebSocket connection behavior during app startup (enabled by default for backward compatibility)
    • Introduced a new suspend function for establishing connections, providing a synchronous-style alternative to existing asynchronous methods with structured error handling

✏️ Tip: You can customize this high-level summary in your review settings.

Adds a new `autoConnect` boolean parameter to the `StreamVideoBuilder`, defaulting to `true`.

When `autoConnect` is set to `false`, the `StreamVideo` client will not automatically attempt to connect upon initialization. This allows for more control over the connection lifecycle, which can be useful in scenarios where a connection is not immediately required.

The `StreamVideoInitHelper` in the demo app is updated to use this new flag, setting `autoConnect` to `false`.
Removes the unused import for `HttpLoggingLevel` from `StreamVideoInitHelper.kt`.
This commit renames the `autoConnect` parameter in `StreamVideoBuilder` to `connectOnInit`.

This change makes the parameter's purpose clearer: it controls whether the SDK attempts to connect to the websocket immediately upon user initialization, rather than upon any automatic condition.

The documentation has also been updated to reflect this new, more precise naming.
@rahul-lohra rahul-lohra self-assigned this Jan 5, 2026
@rahul-lohra rahul-lohra requested a review from a team as a code owner January 5, 2026 12:14
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@rahul-lohra rahul-lohra added the pr:improvement Enhances an existing feature or code label Jan 5, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Walkthrough

The changes introduce a new suspend connect() function to the StreamVideo API alongside the existing asynchronous connectAsync() method. A new connectOnInit parameter controls whether automatic connection occurs during initialization. Updated error handling wraps exceptions in Result types. The demo app defers explicit connection invocation.

Changes

Cohort / File(s) Summary
Connection API & Interface
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt, stream-video-android-core/api/stream-video-android-core.api
Added new public suspend function connect(): Result<Long> to StreamVideo interface, providing a coroutine-based, immediate result form complementing existing connectAsync(): Deferred<Result<Long>>. API signature updated to reflect suspension and Continuation-based invocation.
Connection Implementation & Initialization Control
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt, stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
Added connectOnInit: Boolean = true parameter to StreamVideoBuilder, gating initial WebSocket connection behind a conditional check. StreamVideoClient now implements new suspend connect() function delegating to connectAsync().await(), and updated error handling in connectAsync() to wrap non-token-expired exceptions as ThrowableError within Result types instead of throwing.
Demo Application Usage
demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
Updated StreamVideoBuilder instantiation to pass connectOnInit = false and added explicit manual StreamVideo.instanceOrNull()?.connect() call to defer connection initialization.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A new suspend path hops into view,
Connect when you wish, not just at debut,
Error-wrapped Results, so clean and so neat,
Manual control makes the async complete! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: introducing a connectOnInit flag to control initial WebSocket connection behavior, which is the core purpose of this PR.
Description check ✅ Passed The description includes Goal and Implementation sections that explain the rationale and technical approach. However, the Testing section is vague and lacks detail on how to verify the changes work correctly.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt (1)

94-95: Consider clarifying KDoc wording.

The phrase "as soon as a user is set" could be more precise. The user is set via constructor parameters, and the connection attempt occurs during build() execution. Consider rewording to "during SDK initialization" or "when build() is called" for clarity.

🔎 Suggested KDoc improvement
- * @property connectOnInit A flag that determines if the socket should attempt to connect as soon as a user is set.
+ * @property connectOnInit A flag that determines if the socket should connect during SDK initialization.
  *                      If `false`, the connection will only be established when explicitly requested or if core-sdk feature(s) like audio/video call is used
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b9c9ceb and d23a9ad.

📒 Files selected for processing (3)
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
  • stream-video-android-core/api/stream-video-android-core.api
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,java}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,java}: Use Kotlin with JVM toolchain 17; Java is legacy-only
Use 4-space indentation with no trailing whitespace
Avoid wildcard imports

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,kts}: Use PascalCase for types and Composables (e.g., StreamCallActivity, ParticipantGrid)
Use camelCase for functions and values
Use UPPER_SNAKE_CASE for constants only when truly constant
Prefer explicit visibility modifiers; limit internal leakage across modules
Keep critical RTC paths off the main thread; prefer coroutines with structured scopes
Monitor logging verbosity; rely on StreamVideoImpl.developmentMode for guardrails
Use KDoc (/** ... */) for public APIs and complex subsystems; link to Stream docs when relevant
Group large files with // region judiciously; keep commentary purposeful
Sanitize logs to avoid dumping JWTs, ICE tokens, or call IDs in verbose logs
Pause/resume capture on lifecycle changes; ensure background audio routing is intentional
Validate orientation, aspect ratio, and dynascale handling for both portrait/landscape phones and tablets
Keep concurrency deterministic—use structured coroutines and avoid global scope
Ensure cleanup/teardown paths handle cancellation and failure (important for sockets, queues, retries)

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,java,kts,gradle.kts}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Spotless formatting; ensure custom license headers are in spotless/ directory

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
🧠 Learnings (2)
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Applies to stream-video-android-previewdata/**/*.{kt,kts} : Keep test fixtures in `stream-video-android-previewdata`; avoid duplicating builder logic

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
  • stream-video-android-core/api/stream-video-android-core.api
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Prefer Jetpack Compose for UI (`stream-video-android-ui-compose`); XML views supported via `stream-video-android-ui-xml`

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: base-android-ci / Build
  • GitHub Check: base-android-ci / Run static checks
  • GitHub Check: base-android-ci / Run unit tests
  • GitHub Check: Build / compose apks
  • GitHub Check: compare-sdk-sizes / Compare SDK sizes
🔇 Additional comments (4)
stream-video-android-core/api/stream-video-android-core.api (1)

8468-8469: LGTM! Backward-compatible API addition for connectOnInit.

The new constructor overload correctly appends the connectOnInit boolean (Z) parameter, and the synthetic constructor properly includes it with the default parameter handling. Existing constructor signatures (lines 8465-8467) are preserved, ensuring binary and source compatibility for current SDK consumers.

demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt (1)

335-336: LGTM! Deferred connection aligns with PR objectives.

Setting connectOnInit = false appropriately defers the WebSocket connection for the demo app, avoiding unnecessary connections at startup while preserving push device registration. The SDK will automatically connect when video features are actively used.

stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt (2)

151-151: LGTM! Default value maintains backward compatibility.

The connectOnInit parameter with a default value of true ensures existing integrations continue to connect automatically upon initialization, avoiding breaking changes.


297-304: LGTM! Conditional connection logic is correct.

The implementation properly:

  • Preserves push device registration before the connectOnInit check (lines 294-296)
  • Scopes connection and its error handling within the conditional block
  • Maintains backward compatibility (default behavior unchanged)
  • Only affects non-anonymous users (guarded by line 291 check)

@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-video-android-core 11.94 MB 11.94 MB 0.00 MB 🟢
stream-video-android-ui-xml 5.68 MB 5.68 MB 0.00 MB 🟢
stream-video-android-ui-compose 6.27 MB 6.28 MB 0.02 MB 🟢

Introduces a new `suspend fun connect(): Result<Unit>` method to the `StreamVideo` interface and its implementation in `StreamVideoClient`.

This new function provides a suspending way to establish a WebSocket connection, returning a `Result` to indicate success or failure. This complements the existing `connectAsync` method by offering a more direct, coroutine-friendly alternative for connection management.
This commit introduces a new `suspend fun connect()` to the `StreamVideo` interface. This provides a more convenient and modern way to handle user connections compared to the existing `connectAsync()` which returns a `Deferred`.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In
@stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt:
- Around line 469-482: connect() is missing guest user awaiting and token
refresh handling present in connectAsync(): before calling
socketImpl.connect(user) ensure guestUserJob?.await() is awaited (use the same
withContext(scope.coroutineContext) pattern as connectAsync()), and in the catch
for ErrorResponse detect e.code == TOKEN_EXPIRED and call and return
refreshToken(e) instead of immediately returning a Failure; otherwise preserve
existing error wrapping for other ErrorResponse and Throwable cases.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d23a9ad and e05f9f0.

📒 Files selected for processing (3)
  • stream-video-android-core/api/stream-video-android-core.api
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,java}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,java}: Use Kotlin with JVM toolchain 17; Java is legacy-only
Use 4-space indentation with no trailing whitespace
Avoid wildcard imports

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,kts}: Use PascalCase for types and Composables (e.g., StreamCallActivity, ParticipantGrid)
Use camelCase for functions and values
Use UPPER_SNAKE_CASE for constants only when truly constant
Prefer explicit visibility modifiers; limit internal leakage across modules
Keep critical RTC paths off the main thread; prefer coroutines with structured scopes
Monitor logging verbosity; rely on StreamVideoImpl.developmentMode for guardrails
Use KDoc (/** ... */) for public APIs and complex subsystems; link to Stream docs when relevant
Group large files with // region judiciously; keep commentary purposeful
Sanitize logs to avoid dumping JWTs, ICE tokens, or call IDs in verbose logs
Pause/resume capture on lifecycle changes; ensure background audio routing is intentional
Validate orientation, aspect ratio, and dynascale handling for both portrait/landscape phones and tablets
Keep concurrency deterministic—use structured coroutines and avoid global scope
Ensure cleanup/teardown paths handle cancellation and failure (important for sockets, queues, retries)

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
**/*.{kt,java,kts,gradle.kts}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Spotless formatting; ensure custom license headers are in spotless/ directory

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
🧠 Learnings (1)
📚 Learning: 2025-12-19T14:10:16.577Z
Learnt from: aleksandar-apostolov
Repo: GetStream/stream-video-android PR: 1587
File: stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt:795-798
Timestamp: 2025-12-19T14:10:16.577Z
Learning: In the `rejoin()` function in `stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt`, the design invariant is that `rejoin()` should only be called when there is an active session (`this.session != null`). Therefore, using `this.session!!` is safe and intentional.

Applied to files:

  • stream-video-android-core/api/stream-video-android-core.api
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: compare-sdk-sizes / Compare SDK sizes
  • GitHub Check: base-android-ci / Run static checks
  • GitHub Check: base-android-ci / Run unit tests
  • GitHub Check: base-android-ci / Build
  • GitHub Check: Build / compose apks
🔇 Additional comments (3)
stream-video-android-core/api/stream-video-android-core.api (2)

8469-8470: Constructor additions maintain backward compatibility.

The new constructor overloads correctly add the connectOnInit parameter with a default value (indicated by the synthetic constructor with DefaultConstructorMarker). Existing callers using previous constructor signatures will continue to work with connectOnInit defaulting to true, preserving the original auto-connect behavior.


8409-8411: Public API addition to StreamVideo interface is acceptable.

The new suspend fun connect() method complements the existing connectAsync() and connectIfNotAlreadyConnected() methods, providing a cleaner coroutine-friendly entry point. The JVM signature is correct for a suspend function.

Since StreamVideo is only implemented by the internal StreamVideoClient class, adding this abstract method is safe and does not introduce breaking changes for external users.

stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt (1)

148-148: LGTM: Clean API addition.

The new connect(): Result<Unit> method provides a straightforward coroutine-compatible alternative to connectAsync(), eliminating the need to unwrap a Deferred when immediate connection is desired.

This commit ensures that the `guestUserJob` is awaited before attempting to establish a WebSocket connection.

Additionally, it adds specific handling for token expiration errors (`VideoErrorCode.TOKEN_EXPIRED`). If a token has expired, it now attempts to refresh it and returns a more specific error message.
This commit refactors the `connect()` method in `StreamVideoClient`.

Key changes:
- The `connect()` method now returns `Result<Long>`, representing the duration of the connection process in milliseconds.
- The previous implementation of `connect()` has been extracted into `connectAsync()` which returns a `Deferred<Result<Long>>`.
- The `connect()` method now simply awaits the result of `connectAsync()`.
- Error handling has been unified to catch all `Throwable` exceptions during connection.
Automatically connects the StreamVideo instance for E2E test builds. This change bypasses the need for push notifications to trigger the connection, which are not used in the E2E testing environment.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt (2)

164-169: Consider handling the connection Result and fix grammar.

Two observations:

  1. The connect() call returns Result<Long> but the result is not captured or handled. If the E2E connection fails, it may go unnoticed. Consider logging failures for observability.

  2. Grammar: "E2E tests does not rely" should be "E2E tests do not rely" (plural subject).

🔎 Proposed improvement
                /**
-                * Because E2E tests does not rely on Push Notification
+                * Because E2E tests do not rely on Push Notifications
                 */
                if (StreamBuildFlavorUtil.isE2eTesting) {
-                    StreamVideo.instance().connect()
+                    val result = StreamVideo.instance().connect()
+                    result.onFailure { error ->
+                        Log.e("StreamVideoInitHelper", "E2E auto-connect failed", error)
+                    }
                }

342-342: LGTM!

The single-line TelecomConfig initialization is cleaner and functionally equivalent.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7238e74 and 0b797ac.

📒 Files selected for processing (3)
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideo.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,java}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,java}: Use Kotlin with JVM toolchain 17; Java is legacy-only
Use 4-space indentation with no trailing whitespace
Avoid wildcard imports

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,kts}: Use PascalCase for types and Composables (e.g., StreamCallActivity, ParticipantGrid)
Use camelCase for functions and values
Use UPPER_SNAKE_CASE for constants only when truly constant
Prefer explicit visibility modifiers; limit internal leakage across modules
Keep critical RTC paths off the main thread; prefer coroutines with structured scopes
Monitor logging verbosity; rely on StreamVideoImpl.developmentMode for guardrails
Use KDoc (/** ... */) for public APIs and complex subsystems; link to Stream docs when relevant
Group large files with // region judiciously; keep commentary purposeful
Sanitize logs to avoid dumping JWTs, ICE tokens, or call IDs in verbose logs
Pause/resume capture on lifecycle changes; ensure background audio routing is intentional
Validate orientation, aspect ratio, and dynascale handling for both portrait/landscape phones and tablets
Keep concurrency deterministic—use structured coroutines and avoid global scope
Ensure cleanup/teardown paths handle cancellation and failure (important for sockets, queues, retries)

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,java,kts,gradle.kts}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Spotless formatting; ensure custom license headers are in spotless/ directory

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
🧠 Learnings (2)
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Applies to stream-video-android-previewdata/**/*.{kt,kts} : Keep test fixtures in `stream-video-android-previewdata`; avoid duplicating builder logic

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Prefer Jetpack Compose for UI (`stream-video-android-ui-compose`); XML views supported via `stream-video-android-ui-xml`

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: base-android-ci / Build
  • GitHub Check: base-android-ci / Run unit tests
  • GitHub Check: base-android-ci / Run static checks
  • GitHub Check: compare-sdk-sizes / Compare SDK sizes
  • GitHub Check: Build / compose apks
🔇 Additional comments (2)
demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt (2)

343-343: The connectOnInit = false parameter correctly defers the automatic WebSocket connection. The parameter is properly defined in StreamVideoBuilder with a default value of true, allowing the demo app to explicitly control connection timing as intended.


58-58: Import is valid and properly used.

The StreamBuildFlavorUtil class exists at demo-app/src/main/kotlin/io/getstream/video/android/tooling/util/StreamFlavors.kt with the isE2eTesting property correctly defined. The import and its usage at line 167 are correct.

This commit refactors how the WebSocket connection is managed at application startup.

Previously, the `StreamVideoInitHelper` would automatically connect the client if the build flavor was for E2E testing. This logic is now removed.

Instead, the client is explicitly connected in the `App.kt` `onCreate` method. This change is made to support end-to-end tests that rely on WebSocket events for receiving calls, as the `connectOnInit` flag is set to `false` by default.

Additionally, the documentation for the `connectOnInit` flag in `StreamVideoBuilder` has been improved to clarify its behavior, especially regarding push notifications and manual connection.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In @demo-app/src/main/kotlin/io/getstream/video/android/App.kt:
- Line 74: Avoid blocking the main thread in Application.onCreate by removing
runBlocking around StreamVideo.instanceOrNull()?.connect(); instead create a
background coroutine (e.g., CoroutineScope(Dispatchers.IO +
SupervisorJob()).launch { ... }) and call
StreamVideo.instanceOrNull()?.connect() inside it, capturing the returned
Result<Long> into a val (e.g., val result = ...), then handle both success and
failure cases (log the connection id on success and log the throwable or failure
message on failure) so connection errors are not silent and startup cannot ANR.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0b797ac and 901a622.

📒 Files selected for processing (3)
  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,java}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,java}: Use Kotlin with JVM toolchain 17; Java is legacy-only
Use 4-space indentation with no trailing whitespace
Avoid wildcard imports

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,kts}: Use PascalCase for types and Composables (e.g., StreamCallActivity, ParticipantGrid)
Use camelCase for functions and values
Use UPPER_SNAKE_CASE for constants only when truly constant
Prefer explicit visibility modifiers; limit internal leakage across modules
Keep critical RTC paths off the main thread; prefer coroutines with structured scopes
Monitor logging verbosity; rely on StreamVideoImpl.developmentMode for guardrails
Use KDoc (/** ... */) for public APIs and complex subsystems; link to Stream docs when relevant
Group large files with // region judiciously; keep commentary purposeful
Sanitize logs to avoid dumping JWTs, ICE tokens, or call IDs in verbose logs
Pause/resume capture on lifecycle changes; ensure background audio routing is intentional
Validate orientation, aspect ratio, and dynascale handling for both portrait/landscape phones and tablets
Keep concurrency deterministic—use structured coroutines and avoid global scope
Ensure cleanup/teardown paths handle cancellation and failure (important for sockets, queues, retries)

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,java,kts,gradle.kts}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Spotless formatting; ensure custom license headers are in spotless/ directory

Files:

  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
🧠 Learnings (3)
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Applies to stream-video-android-previewdata/**/*.{kt,kts} : Keep test fixtures in `stream-video-android-previewdata`; avoid duplicating builder logic

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
📚 Learning: 2025-12-19T14:10:16.577Z
Learnt from: aleksandar-apostolov
Repo: GetStream/stream-video-android PR: 1587
File: stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt:795-798
Timestamp: 2025-12-19T14:10:16.577Z
Learning: In the `rejoin()` function in `stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt`, the design invariant is that `rejoin()` should only be called when there is an active session (`this.session != null`). Therefore, using `this.session!!` is safe and intentional.

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/App.kt
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Prefer Jetpack Compose for UI (`stream-video-android-ui-compose`); XML views supported via `stream-video-android-ui-xml`

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build / compose apks
  • GitHub Check: base-android-ci / Run unit tests
  • GitHub Check: base-android-ci / Run static checks
  • GitHub Check: base-android-ci / Build
  • GitHub Check: compare-sdk-sizes / Compare SDK sizes
🔇 Additional comments (6)
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt (3)

94-99: LGTM! Clear documentation.

The KDoc clearly explains the behavior and push notification implications of connectOnInit = false.


155-155: Parameter addition looks good.

The default value of true maintains backward compatibility. Note the past comment about potentially changing the default to false in a future major release.


301-308: LGTM! Conditional connection logic is correct.

The conditional correctly gates the initial WebSocket connection while preserving push device registration and error handling. The implementation maintains existing behavior when connectOnInit = true.

demo-app/src/main/kotlin/io/getstream/video/android/App.kt (1)

66-73: LGTM! Comment clearly explains the explicit connection.

The comment effectively documents why manual connection control is needed for E2E tests.

demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt (2)

335-335: LGTM! Simplified TelecomConfig construction.

The single-line construction is cleaner and aligns with the updated TelecomConfig API.


336-336: LGTM! Consistent with explicit connection in App.kt.

Setting connectOnInit = false here aligns with the explicit connect() call in App.kt, enabling manual connection control for E2E testing scenarios.

* This is required for end-to-end (E2E) tests, which rely on WebSocket events
* to receive calls instead of Push Notifications (PN).
*/
StreamVideo.instanceOrNull()?.connect()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Consider non-blocking connection and error handling.

The runBlocking call in Application.onCreate() can block the main thread during app startup, potentially causing ANR if the connection hangs or takes too long. Additionally, the Result<Long> from connect() is not handled, which could lead to silent failures in E2E tests.

🔎 Recommended approach using a coroutine scope
-            /**
-             * The `connectOnInit` flag in `StreamVideoInitHelper` is set to `false` to give us
-             * manual control over the connection.
-             *
-             * We explicitly call `connect()` here to establish a WebSocket connection at startup.
-             * This is required for end-to-end (E2E) tests, which rely on WebSocket events
-             * to receive calls instead of Push Notifications (PN).
-             */
-            StreamVideo.instanceOrNull()?.connect()
+            /**
+             * The `connectOnInit` flag in `StreamVideoInitHelper` is set to `false` to give us
+             * manual control over the connection.
+             *
+             * We explicitly call `connect()` here to establish a WebSocket connection at startup.
+             * This is required for end-to-end (E2E) tests, which rely on WebSocket events
+             * to receive calls instead of Push Notifications (PN).
+             */
+            CoroutineScope(Dispatchers.IO).launch {
+                StreamVideo.instanceOrNull()?.connect()?.onFailure { error ->
+                    Log.e("App", "Failed to connect WebSocket for E2E tests", error)
+                }
+            }

This approach:

  • Avoids blocking the main thread
  • Logs connection failures for debugging
  • Uses appropriate dispatcher for I/O operations
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
StreamVideo.instanceOrNull()?.connect()
/**
* The `connectOnInit` flag in `StreamVideoInitHelper` is set to `false` to give us
* manual control over the connection.
*
* We explicitly call `connect()` here to establish a WebSocket connection at startup.
* This is required for end-to-end (E2E) tests, which rely on WebSocket events
* to receive calls instead of Push Notifications (PN).
*/
CoroutineScope(Dispatchers.IO).launch {
StreamVideo.instanceOrNull()?.connect()?.onFailure { error ->
Log.e("App", "Failed to connect WebSocket for E2E tests", error)
}
}
🤖 Prompt for AI Agents
In @demo-app/src/main/kotlin/io/getstream/video/android/App.kt around line 74,
Avoid blocking the main thread in Application.onCreate by removing runBlocking
around StreamVideo.instanceOrNull()?.connect(); instead create a background
coroutine (e.g., CoroutineScope(Dispatchers.IO + SupervisorJob()).launch { ...
}) and call StreamVideo.instanceOrNull()?.connect() inside it, capturing the
returned Result<Long> into a val (e.g., val result = ...), then handle both
success and failure cases (log the connection id on success and log the
throwable or failure message on failure) so connection errors are not silent and
startup cannot ANR.

Adds logging to the `StreamVideo.instanceOrNull()?.connect()` call within the demo app. This provides visibility into whether the WebSocket connection was successful or failed, which is useful for debugging.
Moves the manual `StreamVideo.instanceOrNull()?.connect()` call from `App.kt` to `StreamVideoInitHelper.kt`.

This change ensures that the WebSocket connection is established immediately after the Stream Video SDK is initialized. This is a requirement for end-to-end (E2E) tests, which depend on WebSocket events for receiving calls rather than push notifications.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In
@demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt:
- Around line 164-172: The StreamVideo.instanceOrNull()?.connect() call in
StreamVideoInitHelper ignores the Result<Long>, so a failed WebSocket connect
can be silently ignored while "Init successful" is logged; capture and inspect
the Result from connect() (StreamVideo.instanceOrNull()?.connect()), call
onSuccess to log a confirmed "WebSocket connection established" and onFailure to
Log.e the error (or propagate/abort initialization if failure should block
startup) before emitting the existing "Init successful" message.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e68e01e and f3e6500.

📒 Files selected for processing (1)
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,java}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,java}: Use Kotlin with JVM toolchain 17; Java is legacy-only
Use 4-space indentation with no trailing whitespace
Avoid wildcard imports

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{kt,kts}: Use PascalCase for types and Composables (e.g., StreamCallActivity, ParticipantGrid)
Use camelCase for functions and values
Use UPPER_SNAKE_CASE for constants only when truly constant
Prefer explicit visibility modifiers; limit internal leakage across modules
Keep critical RTC paths off the main thread; prefer coroutines with structured scopes
Monitor logging verbosity; rely on StreamVideoImpl.developmentMode for guardrails
Use KDoc (/** ... */) for public APIs and complex subsystems; link to Stream docs when relevant
Group large files with // region judiciously; keep commentary purposeful
Sanitize logs to avoid dumping JWTs, ICE tokens, or call IDs in verbose logs
Pause/resume capture on lifecycle changes; ensure background audio routing is intentional
Validate orientation, aspect ratio, and dynascale handling for both portrait/landscape phones and tablets
Keep concurrency deterministic—use structured coroutines and avoid global scope
Ensure cleanup/teardown paths handle cancellation and failure (important for sockets, queues, retries)

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
**/*.{kt,java,kts,gradle.kts}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Spotless formatting; ensure custom license headers are in spotless/ directory

Files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
🧠 Learnings (2)
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Applies to stream-video-android-previewdata/**/*.{kt,kts} : Keep test fixtures in `stream-video-android-previewdata`; avoid duplicating builder logic

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
📚 Learning: 2025-12-19T09:15:37.269Z
Learnt from: CR
Repo: GetStream/stream-video-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T09:15:37.269Z
Learning: Applies to **/*.{kt,kts} : Monitor logging verbosity; rely on `StreamVideoImpl.developmentMode` for guardrails

Applied to files:

  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build / compose apks
  • GitHub Check: base-android-ci / Run unit tests
  • GitHub Check: compare-sdk-sizes / Compare SDK sizes
  • GitHub Check: base-android-ci / Build
  • GitHub Check: base-android-ci / Run static checks
🔇 Additional comments (1)
demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt (1)

344-345: LGTM! Deferred WebSocket connection aligns with PR objectives.

The connectOnInit = false parameter correctly defers the automatic WebSocket connection during SDK initialization, and the manual connect() call at line 172 ensures the connection is established when needed for E2E tests. The single-line telecomConfig formatting is also clean.

This implementation gives explicit control over the connection lifecycle as intended by the PR.

Comment on lines +164 to +172
/**
* The `connectOnInit` flag in `StreamVideoInitHelper` is set to `false` to give us
* manual control over the connection.
*
* We explicitly call `connect()` here to establish a WebSocket connection at startup.
* This is required for end-to-end (E2E) tests, which rely on WebSocket events
* to receive calls instead of Push Notifications (PN).
*/
StreamVideo.instanceOrNull()?.connect()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the StreamVideo class and its connect() method
fd -e kt -e java | head -20

Repository: GetStream/stream-video-android

Length of output: 2191


🏁 Script executed:

# Search for connect() function definition
rg -B2 -A10 'fun connect\(' --type=kt | head -50

Repository: GetStream/stream-video-android

Length of output: 100


🏁 Script executed:

# Also check the StreamVideoInitHelper file structure around lines 164-172
fd StreamVideoInitHelper -e kt -exec wc -l {} \;

Repository: GetStream/stream-video-android

Length of output: 260


🏁 Script executed:

# Search for connect() function definition in Kotlin files
rg -A10 'fun connect\(' . --type=kt | head -100

Repository: GetStream/stream-video-android

Length of output: 100


🏁 Script executed:

# Find and read StreamVideoInitHelper.kt file
find . -name "StreamVideoInitHelper.kt" -type f

Repository: GetStream/stream-video-android

Length of output: 157


🏁 Script executed:

# Search more broadly for StreamVideo class and connect method
rg 'class StreamVideo' . --type=kt -A5

Repository: GetStream/stream-video-android

Length of output: 100


🏁 Script executed:

# Read the StreamVideoInitHelper.kt file
cat ./demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt

Repository: GetStream/stream-video-android

Length of output: 15472


🏁 Script executed:

# Search for connect() function without type filter
rg -A10 'fun connect\(' . | head -150

Repository: GetStream/stream-video-android

Length of output: 10720


Handle and log the connect() result—it returns Result<Long>, not Unit.

The connect() call returns Result<Long>, but the return value is discarded. The subsequent "Init successful" log (line 173) is misleading if the connection failed. For E2E tests that depend on WebSocket events, a silent connection failure would go undetected.

Extract and check the result:

StreamVideo.instanceOrNull()?.connect()?.onSuccess {
    Log.d("StreamVideoInitHelper", "WebSocket connection established.")
}?.onFailure { error ->
    Log.e("StreamVideoInitHelper", "Failed to establish WebSocket connection.", error)
}

Alternatively, if the connection failure should fail initialization, propagate or handle it explicitly before logging "Init successful."

🤖 Prompt for AI Agents
In
@demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
around lines 164-172, The StreamVideo.instanceOrNull()?.connect() call in
StreamVideoInitHelper ignores the Result<Long>, so a failed WebSocket connect
can be silently ignored while "Init successful" is logged; capture and inspect
the Result from connect() (StreamVideo.instanceOrNull()?.connect()), call
onSuccess to log a confirmed "WebSocket connection established" and onFailure to
Log.e the error (or propagate/abort initialization if failure should block
startup) before emitting the existing "Init successful" message.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
50.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@rahul-lohra rahul-lohra merged commit 8d8100c into develop Jan 6, 2026
17 of 20 checks passed
@rahul-lohra rahul-lohra deleted the chore/rahullohra/manual-connect branch January 6, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:improvement Enhances an existing feature or code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants