Skip to content

Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2 - #1756

Open
rahul-lohra wants to merge 15 commits into
develop-v2from
v2/feature/rahullohra/build-on-sdk-37
Open

Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2#1756
rahul-lohra wants to merge 15 commits into
develop-v2from
v2/feature/rahullohra/build-on-sdk-37

Conversation

@rahul-lohra

@rahul-lohra rahul-lohra commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Goal

Closes #AND-1342

Raise compileSdk/targetSdk from 35 → 37 (Android 17). The installed platform is the stable, minor-versioned android-37.0, which the old toolchain (AGP 8.5.2) cannot even resolve (Failed to find Platform SDK … android-37). API 37 has a hard floor of AGP 9.1, and AGP 9 drops Kotlin 1.9 — so this is necessarily a full toolchain upgrade, not a one-line SDK bump.

Note: this PR depends on the GetStream/stream-build-conventions-android#70 — streamConventions must point at a published version that supports AGP 9 (currently 0.13.2-SNAPSHOT in the catalog; pin to the released version before merge).

Implementation

Toolchain Updates

Component From To Reason
compileSdk / targetSdk 35 37 Target Android 17
android.suppressUnsupportedCompileSdk 34 37 Match the new compileSdk
Android Gradle Plugin 8.10.1 9.1.1 Minimum for API 37 (9.0 caps at 36.1)
Gradle 8.8 9.3.1 Required by AGP 9.1

Dependency bumps forced by Gradle 9 / AGP 9

Dependency From To Reason
androidxComposeBom 2024.11.00 2025.08.01 AGP 9+ requirement
streamLog 1.3.2 1.3.4 Namespace was fixed
androidxMacroBenchmark 1.2.3 1.5.0-alpha07
androidxMacroBenchmark 1.2.3 1.5.0-alpha07
paparazzi 1.3.4 2.0.0-alpha05 No stable version yet
baseline-profile / benchmark 1.2.3 1.5.0-alpha07 Older versions can't resolve AGP 9's TestExtension
Hilt / Dagger 2.56.2 2.60.1 2.52's bytecode transform doesn't run under AGP 9
streamConventions (build-conventions plugin) 0.13.1 AGP-9-compatible build 0.13.1 calls block-DSLs removed from AGP 9's CommonExtension
stream-log-android 1.3.1 1.3.4 To fix shared namespace for io.getstream.log as AGP 9 gives hard error if two different libraries share same namespace

Dependent Stream Repositories

Dependency From To Reason
streamConventions 0.13.1 0.13.2-SNAPSHOT 0.13.1 calls block-DSLs removed from AGP 9's CommonExtension .We need support for Java 21 (the version will be updated soon)

Library Specific Updates

Paparazzi

  1. Re-record golden images: Paparazzi now depends on CompileSdk 37, which uses an updated layoutlib rendering engine. As a result, all Paparazzi golden images need to be re-recorded.
  2. Add a TrustManagerImpl TrustManagerImpl.java‎.

Robolectric

  1. Add a ‎robolectric.properties‎ file.

🎨 UI Changes

None

Testing

WIP

Summary by CodeRabbit

  • New Features

    • Added support for Android SDK and target API 37.
    • Improved Compose Preview and visual snapshot test compatibility.
    • Added a workflow for recording and reviewing updated visual snapshots.
  • Bug Fixes

    • Improved dependency resolution to prevent logging-library namespace conflicts.
    • Increased compatibility with newer Android build and Compose tooling.
  • Chores

    • Updated major build, testing, and Android development tools.
    • Standardized automated builds on Java 21.

@rahul-lohra rahul-lohra self-assigned this Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

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, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

The metrics module uses the plain `io.getstream.video.android.application`
convention (not the `.compose` variant), so `configureAndroidCompose()`
never runs and the Compose BOM is not applied. Its compose flavors added
unversioned Compose artifacts (foundation, ui, ui-tooling) whose versions
come from the BOM, so resolution failed with:

  Could not find androidx.compose.foundation:foundation:

Add the BOM platform to each compose flavor's Implementation configuration
so the unversioned artifacts resolve.
@rahul-lohra rahul-lohra changed the title Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2 [AND-1342] Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2 Jul 29, 2026
@rahul-lohra rahul-lohra changed the title [AND-1342] Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2 Build on compileSdk/targetSdk 37 (Android 17): AGP 9.1 + Gradle 9.3 + Kotlin 2.2 Jul 29, 2026
Pointing the baseline-profile output/source dir at src/main made AGP 9's
prepareReleaseArtProfile recursively parse every file under it (res webp,
*.kt) as ART profile rules, failing with "Illegal token". Use the default
generated/baselineProfiles dir instead.
@rahul-lohra rahul-lohra added the pr:internal Internal or infra-only changes label Jul 30, 2026
jobs:
base-android-ci:
uses: GetStream/stream-build-conventions-android/.github/workflows/android-ci.yml@v0.13.1
uses: GetStream/stream-build-conventions-android/.github/workflows/android-ci.yml@feature/rahullohra/build-on-sdk-37
java-version: '21' # Paparazzi 2.0.0-alpha05 requires JDK 21.
distribution: temurin
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
jobs:
compare-sdk-sizes:
uses: GetStream/stream-build-conventions-android/.github/workflows/sdk-size-checks.yml@v0.13.1
uses: GetStream/stream-build-conventions-android/.github/workflows/sdk-size-checks.yml.yml@feature/rahullohra/build-on-sdk-37
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
25.0% Coverage on New Code (required ≥ 80%)
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@rahul-lohra
rahul-lohra marked this pull request as ready for review August 10, 2026 06:15
@rahul-lohra
rahul-lohra requested a review from a team as a code owner August 10, 2026 06:15
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR upgrades Gradle, AGP, Android SDK, dependencies, convention plugins, managed devices, CI Java versions, and Paparazzi support. It also adds a workflow for recording and uploading Paparazzi snapshots.

Changes

Android build and validation upgrade

Layer / File(s) Summary
Toolchain versions and repositories
gradle/libs.versions.toml, gradle.properties, gradle/wrapper/..., settings.gradle.kts
The project updates Gradle, AGP, SDK, Compose, Wire, Hilt, Paparazzi, and related versions. Repository resolution and AGP 9 compatibility settings also change.
Convention and module migration
build-logic/..., benchmark/build.gradle.kts, stream-video-android-core/build.gradle.kts, demo-app/build.gradle.kts, metrics/..., build.gradle.kts
Convention plugins use updated Android and Kotlin APIs. Managed devices use localDevices. Compose dependencies use the BOM. The pre-push hook uses Gradle file APIs.
Preview and Paparazzi support
stream-video-android-ui-compose/..., stream-video-android-core/src/test/...
Paparazzi and Compose Preview receive trust-manager stubs and Robolectric SDK 24 settings. Baseline-profile output uses the AGP default directory.
CI and device workflows
.github/workflows/*
Existing workflows use Java 21 and SDK 37 workflow revisions. A new workflow records Paparazzi snapshots and uploads them for seven days.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant Gradle
  participant Paparazzi
  participant ArtifactStorage
  GitHubActions->>Gradle: Run cleanRecordPaparazziDebug
  Gradle->>Paparazzi: Generate golden snapshots
  Paparazzi-->>Gradle: Write snapshot files
  GitHubActions->>ArtifactStorage: Upload snapshot artifact
Loading

Poem

A rabbit hops through Gradle’s gate,
With Java twenty-one to set the rate.
Snapshots bloom in Paparazzi light,
Then artifacts fly away at night.
SDK thirty-seven joins the tune.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary Android SDK and build toolchain upgrade.
Description check ✅ Passed The description covers the goal, implementation, UI status, and testing state for the toolchain upgrade.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v2/feature/rahullohra/build-on-sdk-37

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gradle/libs.versions.toml`:
- Line 11: Update gradle/libs.versions.toml:11 so streamConventions uses the
approved published AGP 9-compatible version instead of a SNAPSHOT. Update
settings.gradle.kts:8-21 to remove local-first/unrestricted snapshot plugin
resolution from the default merge path, or restrict it to an explicit
developer-only override.

In
`@stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/GenericCallActionBroadcastReceiver.kt`:
- Line 85: Ensure the async broadcast is completed when streamCallId is missing:
update the handling around the streamCallId check in
GenericCallActionBroadcastReceiver so the pending result is finished before
logging and returning, or only invoke goAsync() in the branch that launches the
coroutine and finishes it.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 337ffc27-e2b9-46b4-9d66-3c0a1d16e0a0

📥 Commits

Reviewing files that changed from the base of the PR and between 35e5836 and 167eed3.

⛔ Files ignored due to path filters (138)
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot AudioCallContent in default state.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot AudioCallContent without header.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot AudioOnlyCallContent in default state.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot AudioOnlyCallContent without header.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot_AudioCallContent_in_default_state.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioCallContentTest_snapshot_AudioCallContent_without_header.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot AudioAppBar composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot AudioControlActions composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot AudioParticipantsGrid composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot AudioRoom DarkMode composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot AudioRoom composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot_AudioAppBar_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot_AudioControlActions_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AudioRoomTest_snapshot_AudioParticipantsGrid_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AvatarTest_snapshot AvatarInitial composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AvatarTest_snapshot UserAvatar composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AvatarTest_snapshot_AvatarInitial_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_AvatarTest_snapshot_UserAvatar_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Badges with buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Badges_with_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Button with icons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Button_with_icons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Different size buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Different_size_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Generic container (for info messages).png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Generic_container_(for_info_messages).png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Input fields.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Input_fields.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Regular buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Regular icon buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Regular_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Regular_icon_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Show progress into icon buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Show_progress_into_icon_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Toggle buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Toggle icon buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Toggle_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_BaseComponentsTest_Toggle_icon_buttons.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot CallAppBar composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot CallControls composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot RegularCallControls composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot_CallAppBar_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot_CallControls_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallComponentsPortraitTest_snapshot_RegularCallControls_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot CallContent with multiple participants composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallContent Video type with multiple participants composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallContent with minimum parameters.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallContent with one participant composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallContentDetails Audio composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallContentDetails Video composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot IncomingCallOptions composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallContent with minimum parameters and audio type.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallContent with minimum parameters and video type.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallContent with multiple participants composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallContent with one participant composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallDetails Audio composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallDetails Video composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot OutgoingCallOptions composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_CallContent_with_multiple_participants_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallContentDetails_Audio_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallContentDetails_Video_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallContent_Video_type_with_multiple_participants_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallContent_with_minimum_parameters.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallContent_with_one_participant_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_IncomingCallOptions_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallContent_with_minimum_parameters_and_audio_type.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallContent_with_minimum_parameters_and_video_type.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallContent_with_multiple_participants_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallContent_with_one_participant_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallDetails_Audio_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallDetails_Video_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallContentTest_snapshot_OutgoingCallOptions_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallControlsTest_snapshot CallControls Actions composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallControlsTest_snapshot CallControls composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallControlsTest_snapshot_CallControls_Actions_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallControlsTest_snapshot_CallControls_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallLobbyTest_snapshot CallLobby composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_CallLobbyTest_snapshot_CallLobby_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot Connection ConnectionQualityIndicator composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot Connection ParticipantLabel composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot SoundIndicator composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot_Connection_ConnectionQualityIndicator_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot_Connection_ParticipantLabel_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_IndicatorsTest_snapshot_SoundIndicator_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_LivestreamTest_snapshot Livestream Player Overlay composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_LivestreamTest_snapshot Livestream Player composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_LivestreamTest_snapshot_Livestream_Player_Overlay_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_LivestreamTest_snapshot_Livestream_Player_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants1 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants2 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants3 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants4 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants5 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeParticipants6 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeScreenSharingContent for myself composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot LandscapeScreenSharingContent for other participant composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot ParticipantsRow composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_LandscapeParticipants4_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_LandscapeParticipants5_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_LandscapeParticipants6_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_LandscapeScreenSharingContent_for_myself_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_LandscapeScreenSharingContent_for_other_participant_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantLandscapeTest_snapshot_ParticipantsRow_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot CallParticipant a local call composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot CallParticipant a remote call composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot CallParticipantsInfoAppBar composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot CallParticipantsInfoOptions composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot CallParticipantsList composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot InviteUserList composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot LocalVideoContent composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot ParticipantAvatars composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot ParticipantInformation composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot ParticipantVideo composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot ParticipantsColumn composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants1 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants2 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants3 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants4 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants5 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitParticipants6 composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitScreenSharingContent for myself composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot PortraitScreenSharingContent for other participant composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_CallParticipant_a_local_call_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_CallParticipant_a_remote_call_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_CallParticipantsInfoAppBar_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_CallParticipantsInfoOptions_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_CallParticipantsList_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_InviteUserList_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_LocalVideoContent_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_ParticipantAvatars_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_ParticipantInformation_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_ParticipantVideo_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_ParticipantsColumn_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_PortraitParticipants4_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_PortraitParticipants5_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_PortraitParticipants6_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_PortraitScreenSharingContent_for_myself_composable.png is excluded by !**/*.png
  • stream-video-android-ui-compose/src/test/snapshots/images/io.getstream.video.android.compose_ParticipantsPortraitTest_snapshot_PortraitScreenSharingContent_for_other_participant_composable.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • .github/workflows/android.yml
  • .github/workflows/app-distribute.yml
  • .github/workflows/e2e-build.yml
  • .github/workflows/e2e-test-cron.yml
  • .github/workflows/e2e-test.yml
  • .github/workflows/internal-app-distribute.yml
  • .github/workflows/record-paparazzi.yml
  • .github/workflows/sdk-size-checks.yml
  • benchmark/build.gradle.kts
  • build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt
  • build-logic/convention/src/main/kotlin/io/getstream/video/AndroidCompose.kt
  • build-logic/convention/src/main/kotlin/io/getstream/video/DemoFlavor.kt
  • build-logic/convention/src/main/kotlin/io/getstream/video/KotlinAndroid.kt
  • build.gradle.kts
  • demo-app/build.gradle.kts
  • gradle.properties
  • gradle/libs.versions.toml
  • gradle/wrapper/gradle-wrapper.properties
  • metrics/stream-video-android-metrics/build.gradle.kts
  • settings.gradle.kts
  • stream-video-android-core/build.gradle.kts
  • 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/notifications/internal/receivers/GenericCallActionBroadcastReceiver.kt
  • stream-video-android-core/src/test/resources/robolectric.properties
  • stream-video-android-ui-compose/api/stream-video-android-ui-compose.api
  • stream-video-android-ui-compose/build.gradle.kts
  • stream-video-android-ui-compose/src/debug/java/com/android/org/conscrypt/TrustManagerImpl.java
  • stream-video-android-ui-compose/src/test/java/com/android/org/conscrypt/TrustManagerImpl.java
  • stream-video-android-ui-compose/src/test/resources/robolectric.properties

Comment thread gradle/libs.versions.toml
cameraCamera2 = "1.3.4"
spotless = "6.21.0"
streamConventions = "0.13.1"
streamConventions = "0.13.2-SNAPSHOT"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🌐 Web query:

What published non-SNAPSHOT version of the io.getstream.projectGradle plugin is compatible with Android Gradle Plugin 9.1.1? Confirm whether version0.13.2 is published.

💡 Result:

The io.getstream.project Gradle plugin version 0.13.2 is not confirmed to be published; search results only verify the existence and publication of versions up to 0.13.1 [1]. There is no publicly documented information specifying a direct compatibility mapping between specific versions of the io.getstream.project plugin and Android Gradle Plugin (AGP) 9.1.1. The plugin, which serves as a collection of build conventions (stream-build-conventions-android), is typically updated by the Stream team to support newer AGP versions as they are released [2][3][4]. To use the latest available features or compatibility, it is recommended to check the official GetStream GitHub repository for the most recent releases [2][5][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== git status =="
git status --short

echo "== gradle/libs.versions.toml relevant lines =="
nl -ba gradle/libs.versions.toml | sed -n '1,35p;235,255p'

echo "== settings.gradle.kts relevant lines =="
nl -ba settings.gradle.kts | sed -n '1,45p'

echo "== declarations / usages of streamConventions =="
rg -n "streamConventions|gradlePluginPortal|mavenLocal|io\.getstream|AGP 9|androidGradlePlugin|agp" -S --glob '!build/**' --glob '!**/build/**' .

echo "== repository availability checks without executing repo code =="
python3 - <<'PY'
import urllib.request, urllib.error
for url in [
    "https://plugins.gradle.org/m2/io/getstream/project/io.getstream.project.gradle.plugin/0.13.2/",
    "https://plugins.gradle.org/m2/io/getstream/project/io.getstream.project.gradle.plugin/0.13.1/",
    "https://repo1.maven.org/maven2/io/getstream/stream-build-conventions-android/0.13.2/",
    "https://central.sonatype.com/repository/maven-snapshots/io/getstream/stream-build-conventions-android/0.13.2-SNAPSHOT/",
]:
    req = urllib.request.Request(url, method="HEAD")
    try:
        with urllib.request.urlopen(req, timeout=20) as r:
            print(url, r.status, r.headers.get("Content-Type"))
    except urllib.error.HTTPError as e:
        print(url, e.code, e.reason)
    except Exception as e:
        print(url, type(e).__name__, e)
PY

Repository: GetStream/stream-video-android

Length of output: 272


🌐 Web query:

GetStream stream-build-conventions-android 0.13.2 published Gradle plugin

💡 Result:

The GetStream stream-build-conventions-android Gradle plugin version 0.13.2 does not appear to be a published release. Publicly available information and dependency update records (such as those from Dependabot and repository pull requests) indicate that the project release series reached at least version 0.13.1 [1][2], but there is no verified evidence of a 0.13.2 version being published or tagged [3][1]. Development activity on the repository shows subsequent commits following 0.13.1, but these have not culminated in a 0.13.2 release in the public ecosystem [3][1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

pwd
echo "== available repo files =="
test -f gradle/libs.versions.toml && echo "gradle/libs.versions.toml exists" || echo "gradle/libs.versions.toml missing"
test -f settings.gradle.kts && echo "settings.gradle.kts exists" || echo "settings.gradle.kts missing"

echo "== gradle/libs.versions.toml relevant lines =="
awk 'NR>=1 && NR<=35 || NR>=235 && NR<=255 { printf "%3d\t%s\n", NR, $0 }' gradle/libs.versions.toml || true

echo "== settings.gradle.kts relevant lines =="
awk 'NR>=1 && NR<=45 { printf "%3d\t%s\n", NR, $0 }' settings.gradle.kts || true

echo "== relevant declarations/usages =="
rg -n "streamConventions|gradlePluginPortal|mavenLocal|io\.getstream|androidGradlePlugin|agp" gradle/libs.versions.toml settings.gradle.kts -S || true

echo "== repository artifact availability checks =="
python3 - <<'PY'
import urllib.request, urllib.error
for url in [
    "https://plugins.gradle.org/m2/io/getstream/project/io.getstream.project.gradle.plugin/0.13.2/",
    "https://plugins.gradle.org/m2/io/getstream/project/io.getstream.project.gradle.plugin/0.13.1/",
    "https://repo1.maven.org/maven2/io/getstream/stream-build-conventions-android/0.13.2/",
    "https://central.sonatype.com/repository/maven-snapshots/io/getstream/stream-build-conventions-android/0.13.2-SNAPSHOT/maven-metadata.xml",
]:
    req = urllib.request.Request(url, method="HEAD", headers={"User-Agent":"coderbob/verification"})
    try:
        with urllib.request.urlopen(req, timeout=20) as r:
            print(url, r.status, r.headers.get("Content-Type"))
    except urllib.error.HTTPError as e:
        print(url, e.code, e.reason)
    except Exception as e:
        print(url, type(e).__name__, e)
PY

Repository: GetStream/stream-video-android

Length of output: 9671


🌐 Web query:

"streamConventions" "gradle/libs.versions.toml"

💡 Result:

In the context of projects maintained by GetStream (such as stream-video-android and stream-chat-android), streamConventions is a version variable defined within the Gradle version catalog (gradle/libs.versions.toml) [1][2]. It serves as the centralized versioning reference for a suite of internal Gradle convention plugins [2][3]. These plugins are designed to standardize build configurations—such as SDK versions, publishing settings, and linting—across various modules to avoid duplication and ensure consistency [2][3][4]. Key details regarding its usage include: 1. Centralized Versioning: By declaring streamConventions = "" in the [versions] table of libs.versions.toml, the project maintains a single source of truth for the plugin suite version [2]. 2. Plugin Mapping: In the [plugins] table of the same file, multiple convention plugins are referenced using this version key [1][5]: - stream-project (id = "io.getstream.project") - stream-android-application (id = "io.getstream.android.application") - stream-android-library (id = "io.getstream.android.library") - stream-android-test (id = "io.getstream.android.test") - stream-java-library (id = "io.getstream.java.library") - stream-java-platform (id = "io.getstream.java.platform") 3. Implementation: These plugins are typically developed within an included build (often located in a build-logic/ directory) [2][4]. They are not intended for general-purpose use by external projects, as they contain specific configurations tailored to GetStream's internal workflows [3].

Citations:


🌐 Web query:

"streamConventions" "0.13.2-SNAPSHOT"

💡 Result:

The term streamConventions refers to a suite of Gradle build convention plugins and shared GitHub Actions workflows maintained by GetStream, located in the repository GetStream/stream-build-conventions-android [1][2][3]. These plugins are used to standardize build configurations, dependency management, publishing, and CI/CD pipelines across various GetStream Android and Java projects [3][4][5]. The version string 0.13.2-SNAPSHOT represents a development (snapshot) build of this library, which typically follows the release of version 0.13.0 [1][6]. Developers commonly reference these conventions in their projects using version catalogs (e.g., gradle/libs.versions.toml) and by referencing the reusable workflow actions in their.github/workflows/ directory [3][7]. As of August 2026, these conventions are actively used to manage tasks such as Maven publishing, spotless code formatting, and automated dependency updates via Dependabot [1][3][5].

Citations:


Use a published Stream Conventions version for merge builds.

This catalog entry points Stream plugins to a non-public SNAPSHOT, and settings.gradle.kts makes local io.getstream artifacts take precedence over resolved builds. Use the approved published AGP 9-compatible version for streamConventions, and remove local-first/unrestricted snapshot resolution from the default merge path.

  • gradle/libs.versions.toml#L11: set streamConventions to a published compatible version.
  • settings.gradle.kts#L8-L21: remove local-first plugin resolution for merge builds, or make it an explicit developer-only override.
📍 Affects 2 files
  • gradle/libs.versions.toml#L11-L11 (this comment)
  • settings.gradle.kts#L8-L21
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradle/libs.versions.toml` at line 11, Update gradle/libs.versions.toml:11 so
streamConventions uses the approved published AGP 9-compatible version instead
of a SNAPSHOT. Update settings.gradle.kts:8-21 to remove
local-first/unrestricted snapshot plugin resolution from the default merge path,
or restrict it to an explicit developer-only override.

}
} else {
logger.w(createMessage(intentAction, "Stream call ID is not provided."))
logger.w(message = createMessage(intentAction, "Stream call ID is not provided."))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 10 'goAsync\(\)|pendingResult\.finish\(\)|streamCallId != null' \
  stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/GenericCallActionBroadcastReceiver.kt

Repository: GetStream/stream-video-android

Length of output: 2373


🌐 Web query:

Android BroadcastReceiver goAsync finish pending result documentation

💡 Result:

The goAsync method in an Android BroadcastReceiver allows you to defer the completion of a broadcast beyond the return of the onReceive method [1][2]. This is useful for moving long-running operations off the main thread to avoid UI jank [1][3]. When you call goAsync, it returns a BroadcastReceiver.PendingResult object [1][4]. This object represents the active broadcast and must be held until your background work is complete [4][5]. Once your processing is finished, you must call the PendingResult.finish method to inform the system that the broadcast is done and the receiver can be recycled [4][6]. Key considerations include: 1. Time Limits: Even when using goAsync, the broadcast execution time is still limited. The system generally allows up to 10 seconds for the entire operation (including the time spent inside onReceive before calling goAsync and the time until finish is called) [1][2][3]. 2. Threading: The BroadcastReceiver.PendingResult object is not thread-safe, but you can safely pass it to another thread to perform work [4][5]. That thread becomes responsible for calling finish [4][5]. 3. Best Practices: Because of the strict time limits, goAsync is intended for short, immediate tasks. For longer-running background work, the system recommends using other facilities like WorkManager, JobScheduler, or a Service instead [2][3]. Example usage pattern: val pendingResult = goAsync Thread { try { // Perform background work here } finally { pendingResult.finish } }.start

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,110p' stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/GenericCallActionBroadcastReceiver.kt

Repository: GetStream/stream-video-android

Length of output: 4552


Finish the async broadcast also when the call ID is missing.

goAsync() is called before the streamCallId != null check, but the else branch at line 85 only logs and returns without calling pendingResult.finish(). Move goAsync() into the branch where the coroutine finishes the result, or finish the pending result before logging this branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/GenericCallActionBroadcastReceiver.kt`
at line 85, Ensure the async broadcast is completed when streamCallId is
missing: update the handling around the streamCallId check in
GenericCallActionBroadcastReceiver so the pending result is finished before
logging and returning, or only invoke goAsync() in the branch that launches the
coroutine and finishes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:internal Internal or infra-only changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants