> For the complete documentation index, see [llms.txt](https://docs.firework.com/firework-for-developers/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.firework.com/firework-for-developers/android-sdk/integration-guide/compose-support-android.md).

# Compose Support

The Android SDK supplies View-based widgets. Use `AndroidView` to host them in Compose after completing [SDK initialization](/firework-for-developers/android-sdk/integration-guide/getting-started.md). The examples below create each widget in `factory` and release that same instance in `onRelease`.

## Video Feed

Use a `ComponentActivity` or subclass. Register listeners before initialization so that they can receive the first feed result.

```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import com.firework.videofeed.FwVideoFeedView
import com.firework.viewoptions.ViewOptions

@Composable
fun VideoFeed(viewOptions: ViewOptions, modifier: Modifier = Modifier) {
    key(viewOptions) {
        AndroidView(
            modifier = modifier,
            factory = { context ->
                FwVideoFeedView(context).apply {
                    setOnFeedLoadListener { videos ->
                        // Handle the loaded videos.
                    }
                    init(viewOptions)
                }
            },
            onRelease = { view -> view.destroy() },
        )
    }
}
```

Keep `viewOptions` stable with `remember`. Changing the key in this example replaces the widget; ordinary recomposition does not create a new view. If you use the `fwVideoFeedView { viewOptions { ... } }` DSL instead, its `viewOptions` block initializes the view, so register listeners before that block.

See [Configure Video Feed](/firework-for-developers/android-sdk/integration-guide/configure-video-feed.md) for content sources and appearance.

## Storyblock

StoryBlock requires a `FragmentActivity` (or subclass) and a `FragmentManager`. Pass the manager and `LifecycleOwner` explicitly; a Compose `Context` may be a wrapper and should not be cast directly to an Activity.

### Use single storyblock

```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import com.firework.storyblock.FwStoryBlockView
import com.firework.viewoptions.ViewOptions

@Composable
fun StoryblockItem(
    fragmentManager: FragmentManager,
    lifecycleOwner: LifecycleOwner,
    viewOptions: ViewOptions,
    modifier: Modifier = Modifier,
) {
    key(fragmentManager, lifecycleOwner, viewOptions) {
        AndroidView(
            modifier = modifier,
            factory = { context ->
                FwStoryBlockView(context).apply {
                    setOnErrorListener { error ->
                        // Handle SDK errors, including initialization failures.
                    }
                    init(
                        fragmentManager = fragmentManager,
                        lifecycleOwner = lifecycleOwner,
                        viewOptions = viewOptions,
                        pauseWhenNotVisible = true,
                    )
                }
            },
            onRelease = { view -> view.destroy() },
        )
    }
}
```

Use `supportFragmentManager` and the Activity as the owner in an Activity. From a Fragment's Compose view, use `childFragmentManager` and `viewLifecycleOwner`, and dispose that composition with the Fragment view lifecycle.

Example inside a `FragmentActivity` using `setContent` (SDK initialization must already be complete):

```kotlin
setContent {
    val options = remember {
        ViewOptions.Builder()
            .baseOption(BaseOption.Builder().feedResource(FeedResource.Discovery).build())
            .storyBlockOption(
                StoryBlockOption.Builder().enableAutoPlay(true).showFullScreenIcon(true).build()
            )
            .build()
    }
    StoryblockItem(
        fragmentManager = supportFragmentManager,
        lifecycleOwner = this@MyActivity,
        viewOptions = options,
        modifier = Modifier.size(width = 240.dp, height = 400.dp),
    )
}
```

The host above is named `MyActivity`. Import `setContent`, `remember`, `size`, and `dp` from Compose, and the SDK's `FeedResource`, `BaseOption`, `StoryBlockOption`, and `ViewOptions`.

Do not create a StoryBlock on every recomposition or keep detached instances in a long-lived map. Initialize each view once and let `onRelease` destroy it. A new options key deliberately creates a new StoryBlock; do not repeatedly call `init` in `AndroidView.update`.

### Use multiple storyblocks in Grid

Follow the instance guidance in [StoryBlock](/firework-for-developers/android-sdk/integration-guide/storyblock.md): one active StoryBlock per screen is recommended; the documented upper bound is two on newer devices. A lazy layout does not guarantee that only visible items own player resources. The following example is deliberately limited to two items, rather than caching a StoryBlock for every feed entry.

#### Integrate with LazyVerticalGrid Component

Reuse `StoryblockItem` above. `channelId` must be your encoded channel ID. The FragmentManager and owner follow the same Activity/Fragment rules as the single-widget example.

```kotlin
@Composable
fun StoryBlockGrid(
    channelId: String,
    fragmentManager: FragmentManager,
    lifecycleOwner: LifecycleOwner,
) {
    val options = remember(channelId) {
        ViewOptions.Builder()
            .baseOption(BaseOption.Builder().feedResource(FeedResource.Channel(channelId)).build())
            .storyBlockOption(
                StoryBlockOption.Builder().enableAutoPlay(true).showFullScreenIcon(true).build()
            )
            .build()
    }
    LazyVerticalGrid(columns = GridCells.Fixed(2)) {
        items(count = 2, key = { index -> index }) { _ ->
            StoryblockItem(
                fragmentManager = fragmentManager,
                lifecycleOwner = lifecycleOwner,
                viewOptions = options,
                modifier = Modifier.padding(8.dp).height(300.dp),
            )
        }
    }
}
```

Import `LazyVerticalGrid` and `GridCells` from `androidx.compose.foundation.lazy.grid`, along with the Compose layout/runtime imports used in the sample. Each item's `onRelease` handles its own cleanup. For a larger browsable catalog, use [Video Feed](/firework-for-developers/android-sdk/integration-guide/configure-video-feed.md) or [Player Deck](/firework-for-developers/android-sdk/integration-guide/01-basic-usage-and-api.md) instead of creating a StoryBlock per product.

## Player Deck

Player Deck requires additional sizing and scroll-visibility considerations. See [basic usage](/firework-for-developers/android-sdk/integration-guide/01-basic-usage-and-api.md) and [autoplay in scrollable containers](/firework-for-developers/android-sdk/integration-guide/01-basic-usage-and-api/02-autoplay-in-scrollable-containers.md) for complete examples. Do not assume that Compose clipping and traditional View scroll notifications are interchangeable.
