Android TV Integration Skill

Integration conventions for the StreamLayer GoogleTV/AndroidTV SDK that keep an AI agent's diff small and correct — shared setup with Android, screen offset delegate, focus/remote, and Leanback placement.

StreamLayer GoogleTV / AndroidTV SDK Integration

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

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

📘

Android TV shares the Android SDK

GoogleTV and AndroidTV apps use the same io.streamlayer:androidsdk package as mobile. For anything not called out as TV-specific below, follow the Android Integration Skill.

Pick the package

  • io.streamlayer:androidsdk + io.streamlayer:android-media3 — same Maven dependencies as Android, added to your module-level build.gradle.
  • Main UI element: StreamLayerFragment, same as Android — no separate TV fragment class.
  • Requirements: Android Studio 4.0+, target SDK 33+, min SDK 21, Kotlin or Java.

Rules (do this)

  1. Initialize once at launch, with TV defaults. Call StreamLayer.initializeApp(this, SL_SDK_KEY) in Application.onCreate(), then StreamLayer.setGamificationOptions(...) to turn off mobile-oriented features that don't fit a 10-foot UI (global leaderboard, invites, onboarding), and StreamLayer.setCustomTheme(SLRTheme(mainTheme = ..., baseTheme = ...)) to match your TV app's branding. Initialize StreamLayerMedia3Player.initSdk(this) right after.

    • ❌ Reusing your phone theme/gamification defaults unchanged on TV.
    • ✅ TV-specific SLRTheme + gamification options disabled, set once in Application.
  2. Place StreamLayerFragment as a sibling of your Leanback player, not nested inside it. If you use the Leanback library (VideoSupportFragment/PlaybackSupportFragment), add the FragmentContainerView (android:tag="StreamLayerFragment") as its own view alongside the player fragment's container — don't nest it inside Leanback's row/adapter hierarchy, so D-pad focus can move cleanly between your rows and the StreamLayer Element.

  3. Implement the screen-offset delegate instead of fixed TV margins. Register an SLRAppHost.Delegate via withStreamLayerUI { delegate = appHostDelegate } and implement onScreenSizeChanged(size: SLRAppHost.SLRScreenSize) to resize/reposition your player (topMargin, bottomMargin, startMargin, endMargin, playerMinWidth, playerHeight, verticalBias, playerCornerRadius) when the StreamLayer Element opens — don't hardcode TV-safe-area margins yourself.

  4. Let the SDK own D-pad focus and remote input while its Element is active. Don't intercept KEYCODE_DPAD_* events meant for the expanded Element, and don't force focus back to your Leanback rows while it's open. Let your normal focus environment resume once the Element collapses.

  5. Keep credentials and the diff simple. The SDK API Key is a public, client-side value from StreamLayer Studio — a BuildConfig constant is fine; don't add .env scaffolding. Call StreamLayer.createEventSession(eventId, timecodeProvider) when the user switches streams. Fit the Element around your existing TV player screen — don't restructure your Leanback browse/playback flow.

Gotchas

  • Element looks like a phone app. Forgetting to disable mobile gamification options (leaderboard/invites/onboarding) and to set a TV SLRTheme is the most common tell.
  • Fixed-margin layouts break on different TV sets. Use the onScreenSizeChanged screen-offset delegate instead of hardcoded dp margins — screen safe areas vary across GoogleTV/AndroidTV devices.
  • Focus traps. Don't override focus search to pull D-pad focus away from an open StreamLayer Element — the most common Leanback-specific pitfall.
  • StreamLayerFragment used before initializeApp() crashes — same as mobile Android; order matters in Application.onCreate().
  • GoogleTV vs AndroidTV. They share the same OS and Play Store catalog — no separate build or SDK path is needed for either.
  • Authoritative API details: the streamlayer-docs MCP (search / fetch) and the Android Integration Guide.

Related