Android Integration Skill

Integration conventions for the StreamLayer Android SDK that keep an AI agent's diff small and correct — where to initialize, where to place StreamLayerFragment, delegate wiring, and minimal-diff placement.

StreamLayer Android SDK Integration

How to wire StreamLayer into an existing Android app cleanly. Follow the rules — they prevent the common over-integration mistakes.

This page is the human-readable form of the streamlayer-android-integration agent skill. Reference it from your AI agent alongside the streamlayer-docs MCP — see Integrate with an AI Agent.

Pick the package

  • io.streamlayer:androidsdk — the Android SDK, distributed via the public Maven repository (mavenCentral() + maven { url "https://jitpack.io" }).
  • Main UI element: StreamLayerFragment (io.streamlayer.sdk.main.StreamLayerFragment) — the StreamLayer Element container, placed with a FragmentContainerView tagged android:tag="StreamLayerFragment".
  • Player extension (pick one): io.streamlayer:android-media3 or io.streamlayer:android-exoplayer — or implement SLRVideoPlayerProvider yourself if you use a different player.
  • Requirements: Android Studio 4.0+, target SDK 33+, min SDK 23, Kotlin or Java.

Rules (do this)

  1. Initialize once and high; place the fragment low. Call StreamLayer.initializeApp(this, SDK_KEY) exactly once in your Application.onCreate(). Initialize your player extension (StreamLayerMedia3Player.initSdk(this) / StreamLayerExoPlayer.initSdk(this)) right after. Add StreamLayerFragment inside the player screen's layout — the one that owns the video — not as a global singleton fragment.

    • ❌ Adding StreamLayerFragment before StreamLayer.initializeApp() runs — this crashes the app.
    • initializeApp in Application; StreamLayerFragment declared in the player activity's layout.
  2. Place StreamLayerFragment with FragmentContainerView, anchored to your player. Use android:tag="StreamLayerFragment" on every version of the fragment. In portrait, pin its top to the player view and set overlayHeightSpace (via withStreamLayerUI { }) from a layout listener so the expanded Element stops at the player's bottom edge. In landscape, let it go full-screen and pick a side with overlayLandscapeMode.

  3. Wire only the SLRAppHost.Delegate callbacks your app needs. Set it with withStreamLayerUI { delegate = appHostDelegate } and clear it (delegate = null) in onDestroy(). Implement requestAudioDucking(level) / disableAudioDucking() / setAudioVolume(value) / getAudioVolumeListener() for the player-audio bridge, requestStream(id) if the SDK can request a stream switch, and onScreenSizeChanged(size) only if you use OverlayLandscapeMode.LBAR.

  4. Forward authentication after init. For logged-in users, call StreamLayer.authorizationBypass(schema, token) from a coroutine; for guests use StreamLayer.useAnonymousAuth(). Both throw RuntimeException on failure — always wrap in runCatching/try-catch. Implement SLRAuthRequestHandler.onAuthRequired() only if you want to handle the SDK's own auth-required prompt (e.g. by opening StreamLayerAuthActivity).

  5. Keep credentials and the diff simple. The SDK API Key is a public, client-side value from StreamLayer Studio — a constant or your existing config is fine; don't add .env scaffolding. Call StreamLayer.createEventSession(eventId, timecodeProvider) when the user switches streams (timecodeProvider is optional, only needed for spoiler prevention). Fit the fragment around your existing player and layout — don't restructure the app or refactor unrelated view code.

Gotchas

  • App crashes on StreamLayerFragment inflate. Almost always StreamLayer.initializeApp() hasn't run yet — the fragment's component builder depends on an initialized SDK context.
  • Expanded Element covers the player. Missing overlayHeightSpace update in portrait mode — wire the layout listener described in the Layout Guide.
  • Two player extensions installed. Only add one of android-media3 or android-exoplayer — mixing both causes dependency conflicts.
  • authorizationBypass / useAnonymousAuth silently crash. Both throw RuntimeException — always catch it.
  • Delegate stops firing. SLRAppHost.Delegate must stay assigned for as long as the screen is visible; clear it in onDestroy(), not earlier.
  • Authoritative API details: the streamlayer-docs MCP (search / fetch) and the API Reference.

Related