
media3-cast-integration
Implements Google Cast support in Android apps using Jetpack Media3. Handles adding build dependencies, updating manifest, configuring OptionsProvider, and managing CastPlayer or RemoteCastPlayer for playback in both Compose and View-based UIs. Use when adding Cast functionality or migrating from legacy Cast SDK to Media3 Cast.
- Installs
- 798
- Last 24h
- +14
- Trending rank
- #7190
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/android/skills --skill media3-cast-integration- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads media3-cast-integration automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Prerequisites
- Jetpack Media3 version must be
>= 1.9.0. Cast isn't available in lower versions.
Glossary
CastPlayer: Media3Playerthat controls playback on both local and remote Cast devices.RemoteCastPlayer: Media3Playerthat communicates with a Cast receiver, only used for remote playback.- Google Cast SDK: Legacy casting SDK in maintenance mode, superseded by Jetpack Media3.
OptionsProvider: Interface providing configuration options to initialize GMSCastContext.
Common guidelines
- Legacy Google Cast SDK is in maintenance mode.
- For new Cast setups:
- You must use Jetpack Media3 Cast.
- You mustn't use legacy Cast SDK unless explicitly requested.
Step 1: Set up dependencies
To complete this step, you MUST ensure the following:
-
In the app-level build file, declare the
media3-castdependency version 1.9.0 or higher.implementation("androidx.media3:media3-cast:1.11.1") -
Ensure required Media3 dependencies are present:
androidx.media3:media3-exoplayerandroidx.media3:media3-sessionandroidx.media3:media3-ui-compose
-
If the application uses legacy Views, add
media3-ui. -
Enforce the same versions across all Media3 dependencies.
-
Use configurations in "Add build dependencies" section of Getting started with CastPlayer as the source of truth.
-
For apps without an existing Cast integration:
- Verify legacy Cast SDK (
libs.play.services.cast.framework) is absent.
- Verify legacy Cast SDK (
-
If Migrating from Legacy Cast SDK:
- Add Media3 Cast dependencies first.
- Keep existing legacy dependencies untouched at this stage to prevent compilation errors.
Step 2: Update the manifest
To complete this step, you MUST ensure the following:
- Inside the manifest's
<application>tag, declare the Cast options provider. - Use
DefaultCastOptionsProviderby default. See the "OptionsProvider" section in Getting started with CastPlayer. - Declare a custom
OptionsProvideronly if explicitly requested. See Customize CastOptions. - Ensure
INTERNETpermission is present. Don't add any unnecessary permissions. - If Migrating from Legacy Cast SDK:
- Don't delete existing custom options provider files or manifest entries.
Step 3: Implement the player and service
Architecture baseline
Before integrating Media3 Cast, an existing app follows one of two setups:
- Local-only playback: Uses Media3
ExoPlayeronly to support local playback. - Legacy Cast setup: Uses
ExoPlayerfor local playback, alongside aPlayerwrapper over the legacyRemoteMediaClientfor remote playback. The UI interfaces with aMediaSessioninteracting with aForwardingPlayer, which finally routes controls to either local or remote playback.
To complete this step, you MUST ensure the following:
- Inside the application's
MediaSessionService(orMediaLibraryService)onCreate()method, initializeExoPlayerandCastPlayer. - Use
CastPlayerby default unlessRemoteCastPlayeris explicitly requested. See the "Build a CastPlayer" section in Getting started with CastPlayer. - For
CastPlayer, pass the instance directly toMediaSession.Builder. - Replace all legacy forwarding player wrappers.
- Don't delete legacy class files yet to prevent compilation errors during migration.
Advanced: RemoteCastPlayer
-
Use
RemoteCastPlayeronly if explicitly requested by user. -
Initialize
MediaSessionwithlocalPlayerand set aSessionAvailabilityListeneronRemoteCastPlayerto transfer playback state on Cast session availability changes:class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null private lateinit var localPlayer: ExoPlayer private lateinit var remotePlayer: RemoteCastPlayer
override fun onCreate() { super.onCreate() localPlayer = ExoPlayer.Builder(this).build() remotePlayer = RemoteCastPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, localPlayer).build() remotePlayer.setSessionAvailabilityListener( object : SessionAvailabilityListener { override fun onCastSessionAvailable() { transferPlaybackState(localPlayer, remotePlayer) } override fun onCastSessionUnavailable() { transferPlaybackState(remotePlayer, localPlayer) } } ) } private fun transferPlaybackState(previousPlayer: Player, newPlayer: Player) { if (previousPlayer.mediaItemCount > 0) { val transferStateBuilder = PlayerTransferState.builderFromPlayer(previousPlayer) if (previousPlayer.playbackState == Player.STATE_ENDED || previousPlayer.currentPosition == C.TIME_END_OF_SOURCE) { transferStateBuilder.setCurrentMediaItemIndex(0) transferStateBuilder.setCurrentPosition(0) } transferStateBuilder.build().setToPlayer(newPlayer) } previousPlayer.stop() previousPlayer.clearMediaItems() newPlayer.prepare() mediaSession?.setPlayer(newPlayer) }}
Step 4: Set up the UI
Compose-based UI
To complete this step, you MUST ensure the following:
-
See the "Add a MediaRouteButton Composable to the Player" section in Getting started with CastPlayer for Compose integration guidelines.
-
Use the
MediaRouteButtoncomposable fromandroidx.media3.castpackage. -
Don't use
AndroidViewin the Compose UI hierarchy. -
Place
MediaRouteButtonin an area next to playback controls. Don't hide it behind system UI. -
Don't use
PlayerSurfacefor custom player UI. Use the Material3Playercomposable. -
Force recomposition on playback location shifts to ensure UI sync. Use key constraints on
DeviceInfochanges:@OptIn(UnstableApi::class) @Composable fun MainScreen() { val player = rememberMediaController() val deviceInfo = rememberDeviceInfo(player) player?.let { activePlayer -> key(deviceInfo) { PlayerScreen(player = activePlayer) } } } @Composable private fun rememberMediaController(): Player? { // Logic to connect MediaController to MediaSession and release it } @Composable private fun rememberDeviceInfo(player: Player?): DeviceInfo? { var deviceInfo by remember(player) { mutableStateOf(player?.deviceInfo) } DisposableEffect(player) { val activePlayer = player ?: return@DisposableEffect onDispose {} deviceInfo = activePlayer.deviceInfo val listener = object : Player.Listener { override fun onDeviceInfoChanged(info: DeviceInfo) { deviceInfo = info } } activePlayer.addListener(listener) onDispose { activePlayer.removeListener(listener) } } return deviceInfo }
View-based UI
To complete this step, you MUST ensure the following:
-
For View-based UI setups, see the "Add UI elements" section in Getting started with CastPlayer.
-
Casting Activities must extend
AppCompatActivityorFragmentActivityand use aTheme.AppCompatdescendant. -
Ensure the
AppCompattheme has a visibleActionBarif addingMediaRouteButtonto the options menu. -
Replace all instances and imports of
CastButtonFactorywithMediaRouteButtonFactory. -
Rebind
PlayerView.playerreferences upononDeviceInfoChangedevents to prevent black screens or UI freezes:private val playerListener: Player.Listener = object : Player.Listener { override fun onDeviceInfoChanged(deviceInfo: DeviceInfo) { // Resetting to null bypasses PlayerView.setPlayer()'s instance equality check // (this.player == player), forcing it to re-bind the video surface to the controller. playerView.player = null playerView.player = controller } } -
Migration to Compose:
- Don't use
AndroidViewto wrap the legacyPlayerView. - Implement Material3
Playercomposable andMediaRouteButtoncomposable as per Getting started with CastPlayer. - Remove legacy XML layout declarations, menu files, and View component references.
- Don't use
Step 5: Clean up legacy Cast SDK code
[!WARNING] Warning: Don't perform cleanup directly. Remove legacy files and dependencies only when explicitly requested by the user.
To complete this step, you MUST ensure the following:
- Remove legacy GMS Cast SDK (
libs.play.services.cast.framework) and MediaRouter (libs.androidx.mediarouter) dependencies. - Delete custom
OptionsProviderclasses and manifest entries ifDefaultCastOptionsProvideris adopted. - Remove legacy
MediaTransferReceivermanifest declarations if present. - Remove all references to legacy Cast SDK components such as legacy helper wrappers, forwarding players, and
RemoteMediaClientinterfaces. - Delete legacy View XML layouts, menu files, and references to
PlayerViewif the migration to Compose is complete.
FAQ
What does the media3-cast-integration skill do?
Implements Google Cast support in Android apps using Jetpack Media3. Handles adding build dependencies, updating manifest, configuring OptionsProvider, and managing CastPlayer or RemoteCastPlayer for playback in both Compose and View-based UIs. Use when adding Cast functionality or migrating from legacy Cast SDK to Media3 Cast.
How do I install media3-cast-integration?
Run npx skills add https://github.com/android/skills --skill media3-cast-integration in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/media3-cast-integration/ (personal) or .claude/skills/media3-cast-integration/ (project).
Which AI agents can use media3-cast-integration?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is media3-cast-integration safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains media3-cast-integration?
It is published by android in android/skills. It has 798 recorded installs.
More from android/skills
navigation-3
android/skills
Learn how to install and migrate to Jetpack Navigation 3, and how to implement features and patterns such as deep links, multiple backstacks, scenes (dialogs, bottom sheets, list-detail, two-pane, supporting pane), conditional navigation (such as logged-in navigation versus anonymous), returning results from flows, integration with Hilt, ViewModel, Kotlin, and view interoperability.
edge-to-edge
android/skills
Use this skill to migrate your Jetpack Compose app to add adaptive edge-to-edge support and troubleshoot common issues. Use this skill to fix UI components (like buttons or lists) that are obscured by or overlapping with the navigation bar or status bar, fix IME insets, and fix system bar legibility.
r8-analyzer
android/skills
Analyzes Android build files and R8 keep rules to identify redundancies, broad package-wide rules, and rules that subsume library consumer keep rules. Use this skill when developers want to optimize their Android app's size, remove redundant or overly broad keep rules, or troubleshoot ProGuard configurations. Don't use for general Gradle build errors, Compose UI performance, or runtime CPU profiling.
android-cli
android/skills
Provides instructions for installing and using the android CLI. The android command-line tool is a critical tool for Android development and helps you create new Android projects, install APKs onto devices and emulators and launch and run apps on them, manage and interact with Android virtual devices (including screenshots and UI inspection), manage Android SDK components, look up official Android documentation, and discover and install official Android skills.
testing-setup
android/skills
Analyze and create a testing strategy for Android apps - install testing libraries, set up test infrastructure, create harnesses for unit tests, UI tests, screenshot tests, and end-to-end tests.
adaptive
android/skills
Instructions to make or update an app's UI so that it adapts to different Android devices including phones, tablets, foldables, laptops, desktop, TV, Auto, and XR. It includes how to handle different window sizes, pointing devices (such as mouse) and text entry devices (such as keyboard) using the Compose MediaQuery API, and how to preserve UI, navigation, scroll, and media playback state across configuration changes (such as folding/unfolding a foldable, rotating a device, or resizing a window). It also covers multi-pane layouts using Navigation3 Scenes, adaptive UI components (such as buttons) with varying target sizes, and adaptive layouts (including navigation areas - nav rails and nav bars) using the Compose Grid and FlexBox APIs. It also covers desktop experiences with keyboard shortcuts, tooltips and custom cursors.
Popular mobile skills
design-mobile-apps
designed-by-ai/skills
Design mobile app screens with Sleek, edit Sleek projects, and implement their designs in React Native or HTML.
ios-design
uizze.sh
Design and review iOS UI/UX for iPhone apps in SwiftUI, UIKit, or React Native. Use for mobile app design, screen redesigns, navigation flows, typography, forms, keyboard and safe-area layout, and accessibility checks. Apply Apple Human Interface Guidelines and consult real product references through the optional Uizze connection.
vercel-react-native-skills
vercel-labs/agent-skills
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
animate-expo
emilkowalski/skills
Build animations in React Native and Expo, making the decisions in the order that determines whether they feel right — should it animate, which thread it runs on, which properties, spring or timing, how the gesture hands off, how it degrades. Writes the implementation with Reanimated, Gesture Handler, Expo Router and expo-haptics. Use when animating anything in an Expo app, adding gestures, sheets, screen transitions, press feedback or haptics, or fixing motion that stutters on device. For web animation use animate.
xcode-project-setup
firebase/agent-skills
Safely modifies Xcode projects (.pbxproj) to add Swift Packages and link files. Use this skill whenever an iOS project needs dependencies installed (e.g. Firebase, Alamofire).
firebase-remote-config-basics
firebase/agent-skills
Manages Firebase Remote Config templates, feature flags, loading strategies, and SDKs (Android, iOS). Use when downloading/deploying remoteconfig JSON templates, managing version history/feature flags, setting in-app defaults, fetchAndActivate(), real-time listeners, or SDK setup. Don't use for Firebase Hosting, Auth, Firestore, Data Connect, Crashlytics, or App Hosting.