CINXE.COM

Media3  |  Jetpack  |  Android Developers

<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="721724668570-nbkv1cfusk7kk4eni4pjvepaus73b13t.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="Android Developers"> <meta property="og:type" content="website"><meta name="theme-color" content="#34a853"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/android/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500,600,700|Google+Sans+Text:400,400italic,500,500italic,600,600italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/css/app.css"> <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/css/dark-theme.css" disabled> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/favicon.svg"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/touchicon-180.png"><link rel="canonical" href="https://developer.android.com/jetpack/androidx/releases/media3"><link rel="search" type="application/opensearchdescription+xml" title="Android Developers" href="https://developer.android.com/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://developer.android.com/jetpack/androidx/releases/media3" /><link rel="alternate" hreflang="x-default" href="https://developer.android.com/jetpack/androidx/releases/media3" /><link rel="alternate" hreflang="ar" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=ar" /><link rel="alternate" hreflang="bn" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=fa" /><link rel="alternate" hreflang="fr" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=fr" /><link rel="alternate" hreflang="de" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=de" /><link rel="alternate" hreflang="he" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=he" /><link rel="alternate" hreflang="hi" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=hi" /><link rel="alternate" hreflang="id" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=id" /><link rel="alternate" hreflang="it" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=it" /><link rel="alternate" hreflang="ja" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=ja" /><link rel="alternate" hreflang="ko" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=ko" /><link rel="alternate" hreflang="pl" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=es-419" /><link rel="alternate" hreflang="th" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=th" /><link rel="alternate" hreflang="tr" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=tr" /><link rel="alternate" hreflang="vi" href="https://developer.android.com/jetpack/androidx/releases/media3?hl=vi" /><title>Media3 &nbsp;|&nbsp; Jetpack &nbsp;|&nbsp; Android Developers</title> <meta property="og:title" content="Media3 &nbsp;|&nbsp; Jetpack &nbsp;|&nbsp; Android Developers"><meta property="og:url" content="https://developer.android.com/jetpack/androidx/releases/media3"><meta property="og:image" content="https://developer.android.com/static/images/social/android-developers.png"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="675"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Media3" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Get started", "item": "https://developer.android.com/get-started/overview" },{ "@type": "ListItem", "position": 2, "name": "Jetpack", "item": "https://developer.android.com/jetpack" },{ "@type": "ListItem", "position": 3, "name": "Media3", "item": "https://developer.android.com/jetpack/androidx/releases/media3" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="android-theme" type="article" appearance layout="docs" display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="androidDevelopers" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Android Developers"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg" class="devsite-site-logo" alt="Android Developers"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab class="devsite-dropdown devsite-dropdown-full devsite-active "> <a href="https://developer.android.com/jetpack" track-metadata-eventdetail="https://developer.android.com/jetpack" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - essentials" track-metadata-module="primary nav" aria-label="Essentials, selected" data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" > Essentials </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Essentials" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack" track-metadata-position="nav - essentials" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown android-dropdown-primary android-dropdown-studio"> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>Gemini in Android Studio</li> <li class="devsite-nav-description">Your AI development companion for Android development. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/gemini-in-android" track-type="nav" track-metadata-eventdetail="https://developer.android.com/gemini-in-android" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="gemini in android studio" tooltip class="button button-primary" > <div class="devsite-nav-item-title"> Learn more </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="gemini in android studio" tooltip class="button button-white" > <div class="devsite-nav-item-title"> Get Android Studio </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-launch"> <li class="devsite-nav-title" role="heading" tooltip>Get started</li> <li class="devsite-nav-description">Start by creating your first app. Go deeper with our training courses or explore app development on your own. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/get-started/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/get-started/overview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Hello world </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/courses" track-type="nav" track-metadata-eventdetail="https://developer.android.com/courses" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Training courses </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/get-started/codelabs" track-type="nav" track-metadata-eventdetail="https://developer.android.com/get-started/codelabs" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Tutorials </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/kotlin" track-type="nav" track-metadata-eventdetail="https://developer.android.com/kotlin" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Kotlin for Android </div> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/console/about/guides/monetize/" track-type="nav" track-metadata-eventdetail="https://play.google.com/console/about/guides/monetize/" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get started" tooltip > <div class="devsite-nav-item-title"> Monetization with Play ↗️ </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-multiple-screens"> <li class="devsite-nav-title" role="heading" tooltip>Extend by device</li> <li class="devsite-nav-description">Build apps that give your users seamless experiences from phones to tablets, watches, and more. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/adaptive-apps" track-type="nav" track-metadata-eventdetail="https://developer.android.com/adaptive-apps" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Adaptive apps </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/wear" track-type="nav" track-metadata-eventdetail="https://developer.android.com/wear" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/cars" track-type="nav" track-metadata-eventdetail="https://developer.android.com/cars" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Android for Cars </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/tv" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/chrome-os" track-type="nav" track-metadata-eventdetail="https://developer.android.com/chrome-os" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> ChromeOS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/multi-device-development" track-type="nav" track-metadata-eventdetail="https://developer.android.com/multi-device-development" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="extend by device" tooltip > <div class="devsite-nav-item-title"> Cross-device SDK </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-platform"> <li class="devsite-nav-title" role="heading" tooltip>Build by category</li> <li class="devsite-nav-description">Learn to build for your use case by following Google&#39;s prescriptive and opinionated guidance. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/games" track-type="nav" track-metadata-eventdetail="https://developer.android.com/games" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Games </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/media" track-type="nav" track-metadata-eventdetail="https://developer.android.com/media" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Camera & Media </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/social-and-messaging" track-type="nav" track-metadata-eventdetail="https://developer.android.com/social-and-messaging" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Social & messaging </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/health-and-fitness" track-type="nav" track-metadata-eventdetail="https://developer.android.com/health-and-fitness" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Health & Fitness </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/productivity" track-type="nav" track-metadata-eventdetail="https://developer.android.com/productivity" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Productivity </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/work/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/work/overview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="build by category" tooltip > <div class="devsite-nav-item-title"> Enterprise apps </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-stars"> <li class="devsite-nav-title" role="heading" tooltip>Get the latest</li> <li class="devsite-nav-description">Stay in touch with the latest releases throughout the year, join our preview programs, and give us your feedback. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/latest-updates" track-type="nav" track-metadata-eventdetail="https://developer.android.com/latest-updates" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Latest updates </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/latest-updates/experimental" track-type="nav" track-metadata-eventdetail="https://developer.android.com/latest-updates/experimental" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Experimental updates </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio/preview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio/preview" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Android Studio preview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/versions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/versions" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Jetpack & Compose libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/wearables/versions/4" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/wearables/versions/4" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Wear OS preview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design-for-safety/privacy-sandbox" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design-for-safety/privacy-sandbox" track-metadata-position="nav - essentials" track-metadata-module="tertiary nav" track-metadata-module_headline="get the latest" tooltip > <div class="devsite-nav-item-title"> Privacy Sandbox </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-dropdown-full "> <a href="https://developer.android.com/design" track-metadata-eventdetail="https://developer.android.com/design" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - design &amp; plan" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Design &amp; Plan" track-name="design &amp; plan" > Design &amp; Plan </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Design &amp; Plan" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design" track-metadata-position="nav - design &amp; plan" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Design &amp; Plan" track-name="design &amp; plan" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-layout"> <li class="devsite-nav-title" role="heading" tooltip>UI Design</li> <li class="devsite-nav-description">Design a beautiful user interface using Android best practices.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Design for Android </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/mobile" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/mobile" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Mobile </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/large-screens" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/large-screens" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Large screens (e.g., tablets) </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/widget" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/widget" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Widgets </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/wear" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/wear" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/design/ui/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/design/ui/tv" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="ui design" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-design"> <li class="devsite-nav-title" role="heading" tooltip>Architecture</li> <li class="devsite-nav-description">Design robust, testable, and maintainable app logic and services.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/architecture/intro" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/architecture/intro" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Introduction </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/libraries/view-binding" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/libraries/view-binding" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/navigation/navigation-principles" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/navigation/navigation-principles" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Navigation </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/modularization" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/modularization" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Modularization </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/testing/fundamentals" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/testing/fundamentals" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="architecture" tooltip > <div class="devsite-nav-item-title"> Testing </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-vitals"> <li class="devsite-nav-title" role="heading" tooltip>Quality</li> <li class="devsite-nav-description">Plan for app quality and align with Play store guidelines.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/core-value" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/core-value" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Core value </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/user-experience" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/user-experience" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> User experience </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/technical" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/technical" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Technical quality </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quality/privacy-and-security" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quality/privacy-and-security" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="quality" tooltip > <div class="devsite-nav-item-title"> Security </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-security-2"> <li class="devsite-nav-title" role="heading" tooltip>Security</li> <li class="devsite-nav-description">Safeguard users against threats and ensure a secure Android experience.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/security" track-type="nav" track-metadata-eventdetail="https://developer.android.com/security" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/privacy-and-security/about" track-type="nav" track-metadata-eventdetail="https://developer.android.com/privacy-and-security/about" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Privacy </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/identity" track-type="nav" track-metadata-eventdetail="https://developer.android.com/identity" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Identity </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/security/fraud-prevention" track-type="nav" track-metadata-eventdetail="https://developer.android.com/security/fraud-prevention" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="security" tooltip > <div class="devsite-nav-item-title"> Fraud prevention </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-earth"> <li class="devsite-nav-title" role="heading" tooltip>Build for Billions</li> <li class="devsite-nav-description">Create the best experience for entry-level devices</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/build-for-billions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/build-for-billions" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> Overview </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/docs/quality-guidelines/build-for-billions" track-type="nav" track-metadata-eventdetail="https://developer.android.com/docs/quality-guidelines/build-for-billions" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> About new markets </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/androidgo" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/androidgo" track-metadata-position="nav - design &amp; plan" track-metadata-module="tertiary nav" track-metadata-module_headline="build for billions" tooltip > <div class="devsite-nav-item-title"> Android (Go edition) </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-dropdown-full "> <a href="https://developer.android.com/develop" track-metadata-eventdetail="https://developer.android.com/develop" class="devsite-tabs-content gc-analytics-event android-dropdown-tab" track-type="nav" track-metadata-position="nav - develop" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" > Develop </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="false" aria-label="Dropdown menu for Develop" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop" track-metadata-position="nav - develop" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></a> <div class="devsite-tabs-dropdown" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column android-dropdown android-dropdown-primary android-dropdown-ai"> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>Build AI experiences</li> <li class="devsite-nav-description">Build AI-powered Android apps with Gemini APIs and more. </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/ai" track-type="nav" track-metadata-eventdetail="https://developer.android.com/ai" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="build ai experiences" tooltip class="button button-primary" > <div class="devsite-nav-item-title"> Get started </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-flag"> <li class="devsite-nav-title" role="heading" tooltip>Core areas</li> <li class="devsite-nav-description">Get the samples and docs for the features you need.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/samples" track-type="nav" track-metadata-eventdetail="https://developer.android.com/samples" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Samples </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/quick-guides" track-type="nav" track-metadata-eventdetail="https://developer.android.com/quick-guides" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Try Quick Guidesᵇᵉᵗᵃ </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop/ui" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop/ui" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> User interfaces </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/permissions/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/permissions/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Permissions </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop/background-work" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop/background-work" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Background work </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/data" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/data" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> Data and files </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/develop#core-areas" track-type="nav" track-metadata-eventdetail="https://developer.android.com/develop#core-areas" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="core areas" tooltip > <div class="devsite-nav-item-title"> All core areas ⤵️ </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-tools-2"> <li class="devsite-nav-title" role="heading" tooltip>Tools and workflow</li> <li class="devsite-nav-description">Use the IDE to write and build your app, or create your own pipeline.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/studio/write" track-type="nav" track-metadata-eventdetail="https://developer.android.com/studio/write" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Write and debug code </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/build/gradle-build-overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/build/gradle-build-overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Build projects </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/testing" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/testing" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Test your app </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/topic/performance/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/topic/performance/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Performance </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/tools" track-type="nav" track-metadata-eventdetail="https://developer.android.com/tools" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Command-line tools </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/reference/tools/gradle-api" track-type="nav" track-metadata-eventdetail="https://developer.android.com/reference/tools/gradle-api" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="tools and workflow" tooltip > <div class="devsite-nav-item-title"> Gradle plugin API </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-multiple-screens"> <li class="devsite-nav-title" role="heading" tooltip>Device tech</li> <li class="devsite-nav-description">Write code for form factors. Connect devices and share data.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/large-screens/get-started-with-large-screens" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/large-screens/get-started-with-large-screens" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Large screens (e.g., tablets) </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/wearables" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/wearables" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Wear OS </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/health-and-fitness/guides" track-type="nav" track-metadata-eventdetail="https://developer.android.com/health-and-fitness/guides" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android Health </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/guide/topics/connectivity/cross-device-sdk/overview" track-type="nav" track-metadata-eventdetail="https://developer.android.com/guide/topics/connectivity/cross-device-sdk/overview" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Cross-device SDK </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/cars" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/cars" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android for Cars </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/training/tv" track-type="nav" track-metadata-eventdetail="https://developer.android.com/training/tv" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> Android TV </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/chrome-os/intro" track-type="nav" track-metadata-eventdetail="https://developer.android.com/chrome-os/intro" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="device tech" tooltip > <div class="devsite-nav-item-title"> ChromeOS </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column android-dropdown"> <ul class="devsite-tabs-dropdown-section android-dropdown-section-icon android-dropdown-section-icon-core-library"> <li class="devsite-nav-title" role="heading" tooltip>Libraries</li> <li class="devsite-nav-description">Browse API reference documentation with all the details.</li> <li class="devsite-nav-item"> <a href="https://developer.android.com/reference/packages" track-type="nav" track-metadata-eventdetail="https://developer.android.com/reference/packages" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Android platform </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/explorer" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/explorer" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Jetpack libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developer.android.com/jetpack/androidx/releases/compose" track-type="nav" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/releases/compose" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Compose libraries </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/android/reference/packages" track-type="nav" track-metadata-eventdetail="https://developers.google.com/android/reference/packages" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Google Play services ↗️ </div> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/sdks" track-type="nav" track-metadata-eventdetail="https://play.google.com/sdks" track-metadata-position="nav - develop" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> Google Play SDK index ↗️ </div> </a> </li> </ul> </div> </div> </div> </tab> <tab > <a href="https://developer.android.com/distribute" track-metadata-eventdetail="https://developer.android.com/distribute" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - google play" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Google Play" track-name="google play" > Google Play </a> </tab> <tab > <a href="https://developer.android.com/community" track-metadata-eventdetail="https://developer.android.com/community" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - community" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" > Community </a> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="Jetpack" tenant-name="Android Developers" > <form class="devsite-search-form" action="https://developer.android.com/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-appearance-selector></devsite-appearance-selector> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <a class="devsite-header-link devsite-top-button button gc-analytics-event" href="https://developer.android.com/studio" data-category="Site-Wide Custom Events" data-label="Site header link" > Android Studio </a> <devsite-user enable-profiles id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" aria-label="Lower header breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://developer.android.com/get-started/overview" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Get started" > Get started </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/jetpack" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Jetpack" > Jetpack </a> </li> </ul> </div> </div> <div class="devsite-doc-set-nav-row"> <devsite-tabs class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://developer.android.com/jetpack" track-metadata-eventdetail="https://developer.android.com/jetpack" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - overview" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" > Overview </a> </tab> <tab > <a href="https://developer.android.com/jetpack/getting-started" track-metadata-eventdetail="https://developer.android.com/jetpack/getting-started" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - guides" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" > Guides </a> </tab> <tab > <a href="https://developer.android.com/jetpack/samples" track-metadata-eventdetail="https://developer.android.com/jetpack/samples" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - samples" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Samples" track-name="samples" > Samples </a> </tab> <tab class="devsite-active"> <a href="https://developer.android.com/jetpack/androidx/explorer" track-metadata-eventdetail="https://developer.android.com/jetpack/androidx/explorer" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - libraries" track-metadata-module="primary nav" aria-label="Libraries, selected" data-category="Site-Wide Custom Events" data-label="Tab: Libraries" track-name="libraries" > Libraries </a> </tab> </nav> </devsite-tabs> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" > <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="androidDevelopers" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Android Developers"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg" class="devsite-site-logo" alt="Android Developers"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/jetpack" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Essentials" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Essentials </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Essentials" track-name="essentials" > <span class="devsite-nav-text" tooltip menu="Essentials"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Essentials"> </span> </span> </li> </ul> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/jetpack" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/getting-started" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Guides" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Guides </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/samples" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Samples" track-name="samples" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Samples" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Samples </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/explorer" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Libraries" track-name="libraries" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Libraries" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip menu="_book"> Libraries </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="_book"> </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/design" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Design &amp; Plan" track-name="design &amp; plan" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Design &amp; Plan" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Design &amp; Plan </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Design &amp; Plan" track-name="design &amp; plan" > <span class="devsite-nav-text" tooltip menu="Design &amp; Plan"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Design &amp; Plan"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/develop" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Develop" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Develop </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Develop" track-name="develop" > <span class="devsite-nav-text" tooltip menu="Develop"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Develop"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/distribute" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Google Play" track-name="google play" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play </span> </a> </li> <li class="devsite-nav-item"> <a href="/community" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Community" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Community </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Studio" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Studio </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item"><a href="/jetpack/androidx/explorer" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/explorer" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/explorer" ><span class="devsite-nav-text" tooltip>Explore the libraries</span></a></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Library Releases</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/jetpack/androidx/versions" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions" ><span class="devsite-nav-text" tooltip>Overview</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/versions/all-channel" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions/all-channel" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions/all-channel" ><span class="devsite-nav-text" tooltip>All Channels</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/versions/stable-channel" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions/stable-channel" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions/stable-channel" ><span class="devsite-nav-text" tooltip>Stable Channel</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/versions/rc-channel" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions/rc-channel" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions/rc-channel" ><span class="devsite-nav-text" tooltip>RC Channel</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/versions/beta-channel" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions/beta-channel" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions/beta-channel" ><span class="devsite-nav-text" tooltip>Beta Channel</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/versions/alpha-channel" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/versions/alpha-channel" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/versions/alpha-channel" ><span class="devsite-nav-text" tooltip>Alpha Channel</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Release Notes</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/activity" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/activity" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/activity" ><span class="devsite-nav-text" tooltip>androidx.activity</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/ads" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/ads" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/ads" ><span class="devsite-nav-text" tooltip>androidx.ads</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/annotation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/annotation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/annotation" ><span class="devsite-nav-text" tooltip>androidx.annotation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/appcompat" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/appcompat" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/appcompat" ><span class="devsite-nav-text" tooltip>androidx.appcompat</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/appsearch" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/appsearch" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/appsearch" ><span class="devsite-nav-text" tooltip>androidx.appsearch</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/arch-core" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/arch-core" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/arch-core" ><span class="devsite-nav-text" tooltip>androidx.arch.core</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/asynclayoutinflater" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/asynclayoutinflater" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/asynclayoutinflater" ><span class="devsite-nav-text" tooltip>androidx.asynclayoutinflater</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/autofill" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/autofill" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/autofill" ><span class="devsite-nav-text" tooltip>androidx.autofill</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/benchmark" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/benchmark" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/benchmark" ><span class="devsite-nav-text" tooltip>androidx.benchmark</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/biometric" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/biometric" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/biometric" ><span class="devsite-nav-text" tooltip>androidx.biometric</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/bluetooth" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/bluetooth" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/bluetooth" ><span class="devsite-nav-text" tooltip>androidx.bluetooth</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/browser" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/browser" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/browser" ><span class="devsite-nav-text" tooltip>androidx.browser</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/camera" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/camera" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/camera" ><span class="devsite-nav-text" tooltip>androidx.camera</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/camera-viewfinder" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/camera-viewfinder" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/camera-viewfinder" ><span class="devsite-nav-text" tooltip>androidx.camera.viewfinder</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/car" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/car" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/car" ><span class="devsite-nav-text" tooltip>androidx.car</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/car-app" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/car-app" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/car-app" ><span class="devsite-nav-text" tooltip>androidx.car.app</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/cardview" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/cardview" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/cardview" ><span class="devsite-nav-text" tooltip>androidx.cardview</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/collection" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/collection" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/collection" ><span class="devsite-nav-text" tooltip>androidx.collection</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose" ><span class="devsite-nav-text" tooltip>androidx.compose</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-animation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-animation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-animation" ><span class="devsite-nav-text" tooltip>androidx.compose.animation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-compiler" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-compiler" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-compiler" ><span class="devsite-nav-text" tooltip>androidx.compose.compiler</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-foundation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-foundation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-foundation" ><span class="devsite-nav-text" tooltip>androidx.compose.foundation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-material" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-material" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-material" ><span class="devsite-nav-text" tooltip>androidx.compose.material</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-material3" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-material3" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-material3" ><span class="devsite-nav-text" tooltip>androidx.compose.material3</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-material3-adaptive" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-material3-adaptive" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-material3-adaptive" ><span class="devsite-nav-text" tooltip>androidx.compose.material3.adaptive</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-runtime" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-runtime" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-runtime" ><span class="devsite-nav-text" tooltip>androidx.compose.runtime</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-ui" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-ui" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-ui" ><span class="devsite-nav-text" tooltip>androidx.compose.ui</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/concurrent" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/concurrent" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/concurrent" ><span class="devsite-nav-text" tooltip>androidx.concurrent</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/constraintlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/constraintlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/constraintlayout" ><span class="devsite-nav-text" tooltip>androidx.constraintlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/contentpager" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/contentpager" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/contentpager" ><span class="devsite-nav-text" tooltip>androidx.contentpager</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/coordinatorlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/coordinatorlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/coordinatorlayout" ><span class="devsite-nav-text" tooltip>androidx.coordinatorlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/core" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/core" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/core" ><span class="devsite-nav-text" tooltip>androidx.core</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/core-uwb" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/core-uwb" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/core-uwb" ><span class="devsite-nav-text" tooltip>androidx.core.uwb</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/credentials" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/credentials" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/credentials" ><span class="devsite-nav-text" tooltip>androidx.credentials</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/credentials/registry" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/credentials/registry" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/credentials/registry" ><span class="devsite-nav-text" tooltip>androidx.credentials.registry</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/cursoradapter" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/cursoradapter" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/cursoradapter" ><span class="devsite-nav-text" tooltip>androidx.cursoradapter</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/customview" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/customview" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/customview" ><span class="devsite-nav-text" tooltip>androidx.customview</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/databinding" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/databinding" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/databinding" ><span class="devsite-nav-text" tooltip>androidx.databinding</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/datastore" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/datastore" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/datastore" ><span class="devsite-nav-text" tooltip>androidx.datastore</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/documentfile" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/documentfile" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/documentfile" ><span class="devsite-nav-text" tooltip>androidx.documentfile</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/draganddrop" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/draganddrop" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/draganddrop" ><span class="devsite-nav-text" tooltip>androidx.draganddrop</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/drawerlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/drawerlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/drawerlayout" ><span class="devsite-nav-text" tooltip>androidx.drawerlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/dynamicanimation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/dynamicanimation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/dynamicanimation" ><span class="devsite-nav-text" tooltip>androidx.dynamicanimation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/emoji" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/emoji" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/emoji" ><span class="devsite-nav-text" tooltip>androidx.emoji</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/emoji2" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/emoji2" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/emoji2" ><span class="devsite-nav-text" tooltip>androidx.emoji2</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/enterprise" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/enterprise" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/enterprise" ><span class="devsite-nav-text" tooltip>androidx.enterprise</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/exifinterface" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/exifinterface" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/exifinterface" ><span class="devsite-nav-text" tooltip>androidx.exifinterface</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/fragment" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/fragment" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/fragment" ><span class="devsite-nav-text" tooltip>androidx.fragment</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/games" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/games" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/games" ><span class="devsite-nav-text" tooltip>androidx.games</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/glance" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/glance" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/glance" ><span class="devsite-nav-text" tooltip>androidx.glance</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/graphics" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/graphics" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/graphics" ><span class="devsite-nav-text" tooltip>androidx.graphics</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/gridlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/gridlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/gridlayout" ><span class="devsite-nav-text" tooltip>androidx.gridlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/health" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/health" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/health" ><span class="devsite-nav-text" tooltip>androidx.health</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/health-connect" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/health-connect" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/health-connect" ><span class="devsite-nav-text" tooltip>androidx.health.connect</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/heifwriter" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/heifwriter" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/heifwriter" ><span class="devsite-nav-text" tooltip>androidx.heifwriter</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/hilt" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/hilt" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/hilt" ><span class="devsite-nav-text" tooltip>androidx.hilt</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/ink" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/ink" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/ink" ><span class="devsite-nav-text" tooltip>androidx.ink</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/input" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/input" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/input" ><span class="devsite-nav-text" tooltip>androidx.input</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/interpolator" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/interpolator" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/interpolator" ><span class="devsite-nav-text" tooltip>androidx.interpolator</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/javascriptengine" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/javascriptengine" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/javascriptengine" ><span class="devsite-nav-text" tooltip>androidx.javascriptengine</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/leanback" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/leanback" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/leanback" ><span class="devsite-nav-text" tooltip>androidx.leanback</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/legacy" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/legacy" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/legacy" ><span class="devsite-nav-text" tooltip>androidx.legacy</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/lifecycle" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/lifecycle" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/lifecycle" ><span class="devsite-nav-text" tooltip>androidx.lifecycle</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/lint" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/lint" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/lint" ><span class="devsite-nav-text" tooltip>androidx.lint</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/loader" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/loader" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/loader" ><span class="devsite-nav-text" tooltip>androidx.loader</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/localbroadcastmanager" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/localbroadcastmanager" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/localbroadcastmanager" ><span class="devsite-nav-text" tooltip>androidx.localbroadcastmanager</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/media" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/media" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/media" ><span class="devsite-nav-text" tooltip>androidx.media</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/media2" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/media2" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/media2" ><span class="devsite-nav-text" tooltip>androidx.media2</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/media3" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/media3" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/media3" ><span class="devsite-nav-text" tooltip>androidx.media3</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/mediarouter" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/mediarouter" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/mediarouter" ><span class="devsite-nav-text" tooltip>androidx.mediarouter</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/multidex" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/multidex" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/multidex" ><span class="devsite-nav-text" tooltip>androidx.multidex</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/metrics" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/metrics" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/metrics" ><span class="devsite-nav-text" tooltip>androidx.metrics</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/navigation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/navigation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/navigation" ><span class="devsite-nav-text" tooltip>androidx.navigation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/paging" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/paging" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/paging" ><span class="devsite-nav-text" tooltip>androidx.paging</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/palette" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/palette" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/palette" ><span class="devsite-nav-text" tooltip>androidx.palette</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/pdf" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/pdf" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/pdf" ><span class="devsite-nav-text" tooltip>androidx.pdf</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/percentlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/percentlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/percentlayout" ><span class="devsite-nav-text" tooltip>androidx.percentlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/preference" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/preference" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/preference" ><span class="devsite-nav-text" tooltip>androidx.preference</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/print" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/print" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/print" ><span class="devsite-nav-text" tooltip>androidx.print</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-activity" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-activity" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-activity" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.activity</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-ads" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-ads" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-ads" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.ads</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-plugins" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-plugins" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-plugins" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.plugins</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-sdkruntime" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-sdkruntime" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-sdkruntime" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.sdkruntime</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-tools" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-tools" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-tools" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.tools</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/privacysandbox-ui" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/privacysandbox-ui" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/privacysandbox-ui" ><span class="devsite-nav-text" tooltip>androidx.privacysandbox.ui</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/profileinstaller" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/profileinstaller" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/profileinstaller" ><span class="devsite-nav-text" tooltip>androidx.profileinstaller</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/recommendation" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/recommendation" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/recommendation" ><span class="devsite-nav-text" tooltip>androidx.recommendation</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/recyclerview" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/recyclerview" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/recyclerview" ><span class="devsite-nav-text" tooltip>androidx.recyclerview</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/remotecallback" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/remotecallback" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/remotecallback" ><span class="devsite-nav-text" tooltip>androidx.remotecallback</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/resourceinspection" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/resourceinspection" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/resourceinspection" ><span class="devsite-nav-text" tooltip>androidx.resourceinspection</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/room" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/room" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/room" ><span class="devsite-nav-text" tooltip>androidx.room</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/savedstate" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/savedstate" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/savedstate" ><span class="devsite-nav-text" tooltip>androidx.savedstate</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/security" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/security" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/security" ><span class="devsite-nav-text" tooltip>androidx.security</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/sharetarget" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/sharetarget" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/sharetarget" ><span class="devsite-nav-text" tooltip>androidx.sharetarget</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/slice" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/slice" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/slice" ><span class="devsite-nav-text" tooltip>androidx.slice</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/slidingpanelayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/slidingpanelayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/slidingpanelayout" ><span class="devsite-nav-text" tooltip>androidx.slidingpanelayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/sqlite" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/sqlite" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/sqlite" ><span class="devsite-nav-text" tooltip>androidx.sqlite</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/startup" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/startup" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/startup" ><span class="devsite-nav-text" tooltip>androidx.startup</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/swiperefreshlayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/swiperefreshlayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/swiperefreshlayout" ><span class="devsite-nav-text" tooltip>androidx.swiperefreshlayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/test" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/test" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/test" ><span class="devsite-nav-text" tooltip>androidx.test</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/test-uiautomator" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/test-uiautomator" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/test-uiautomator" ><span class="devsite-nav-text" tooltip>androidx.test.uiautomator</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/textclassifier" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/textclassifier" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/textclassifier" ><span class="devsite-nav-text" tooltip>androidx.textclassifier</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/tracing" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/tracing" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/tracing" ><span class="devsite-nav-text" tooltip>androidx.tracing</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/transition" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/transition" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/transition" ><span class="devsite-nav-text" tooltip>androidx.transition</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/tv" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/tv" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/tv" ><span class="devsite-nav-text" tooltip>androidx.tv</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/tvprovider" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/tvprovider" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/tvprovider" ><span class="devsite-nav-text" tooltip>androidx.tvprovider</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/vectordrawable" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/vectordrawable" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/vectordrawable" ><span class="devsite-nav-text" tooltip>androidx.vectordrawable</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/versionedparcelable" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/versionedparcelable" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/versionedparcelable" ><span class="devsite-nav-text" tooltip>androidx.versionedparcelable</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/viewpager" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/viewpager" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/viewpager" ><span class="devsite-nav-text" tooltip>androidx.viewpager</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/viewpager2" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/viewpager2" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/viewpager2" ><span class="devsite-nav-text" tooltip>androidx.viewpager2</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/wear" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/wear" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/wear" ><span class="devsite-nav-text" tooltip>androidx.wear</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/wear-compose" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/wear-compose" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/wear-compose" ><span class="devsite-nav-text" tooltip>androidx.wear.compose</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/wear-protolayout" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/wear-protolayout" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/wear-protolayout" ><span class="devsite-nav-text" tooltip>androidx.wear.protolayout</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/wear-tiles" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/wear-tiles" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/wear-tiles" ><span class="devsite-nav-text" tooltip>androidx.wear.tiles</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/wear-watchface" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/wear-watchface" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/wear-watchface" ><span class="devsite-nav-text" tooltip>androidx.wear.watchface</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/webkit" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/webkit" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/webkit" ><span class="devsite-nav-text" tooltip>androidx.webkit</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/window" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/window" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/window" ><span class="devsite-nav-text" tooltip>androidx.window</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/window-extensions-core" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/window-extensions-core" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/window-extensions-core" ><span class="devsite-nav-text" tooltip>androidx.window.extensions.core</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/work" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/work" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/work" ><span class="devsite-nav-text" tooltip>androidx.work</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/jetifier" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/jetifier" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/jetifier" ><span class="devsite-nav-text" tooltip>tools.build.jetifier</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Release Note Archive</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/archive" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/archive" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/archive" ><span class="devsite-nav-text" tooltip>Overview</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/archive/test" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/archive/test" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/archive/test" ><span class="devsite-nav-text" tooltip>Test</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/archive/arch" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/archive/arch" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/archive/arch" ><span class="devsite-nav-text" tooltip>Architecture Components</span></a></li><li class="devsite-nav-item"><a href="/jetpack/androidx/releases/archive/androidx" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/archive/androidx" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/archive/androidx" ><span class="devsite-nav-text" tooltip>AndroidX</span></a></li></ul></div></li> <li class="devsite-nav-item"><a href="/jetpack/androidx/compose-roadmap" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/compose-roadmap" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/compose-roadmap" ><span class="devsite-nav-text" tooltip>Jetpack Compose Roadmap</span></a></li> <li class="devsite-nav-item"><a href="/jetpack/androidx/releases/compose-kotlin" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /jetpack/androidx/releases/compose-kotlin" track-type="bookNav" track-name="click" track-metadata-eventdetail="/jetpack/androidx/releases/compose-kotlin" ><span class="devsite-nav-text" tooltip>Jetpack Compose Kotlin Compatibility</span></a></li> </ul> <ul class="devsite-nav-list" menu="Essentials" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Gemini in Android Studio </span> </span> </li> <li class="devsite-nav-item"> <a href="/gemini-in-android" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn more" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn more </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Get Android Studio" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Get Android Studio </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Get started </span> </span> </li> <li class="devsite-nav-item"> <a href="/get-started/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Hello world" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Hello world </span> </a> </li> <li class="devsite-nav-item"> <a href="/courses" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Training courses" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Training courses </span> </a> </li> <li class="devsite-nav-item"> <a href="/get-started/codelabs" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Tutorials" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Tutorials </span> </a> </li> <li class="devsite-nav-item"> <a href="/kotlin" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Kotlin for Android" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Kotlin for Android </span> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/console/about/guides/monetize/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Monetization with Play ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Monetization with Play ↗️ </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Extend by device </span> </span> </li> <li class="devsite-nav-item"> <a href="/adaptive-apps" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Adaptive apps" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Adaptive apps </span> </a> </li> <li class="devsite-nav-item"> <a href="/wear" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/cars" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android for Cars" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android for Cars </span> </a> </li> <li class="devsite-nav-item"> <a href="/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item"> <a href="/chrome-os" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: ChromeOS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > ChromeOS </span> </a> </li> <li class="devsite-nav-item"> <a href="/multi-device-development" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cross-device SDK" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cross-device SDK </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build by category </span> </span> </li> <li class="devsite-nav-item"> <a href="/games" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Games" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Games </span> </a> </li> <li class="devsite-nav-item"> <a href="/media" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Camera &amp; Media" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Camera &amp; Media </span> </a> </li> <li class="devsite-nav-item"> <a href="/social-and-messaging" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Social &amp; messaging" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Social &amp; messaging </span> </a> </li> <li class="devsite-nav-item"> <a href="/health-and-fitness" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Health &amp; Fitness" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Health &amp; Fitness </span> </a> </li> <li class="devsite-nav-item"> <a href="/productivity" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Productivity" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Productivity </span> </a> </li> <li class="devsite-nav-item"> <a href="/work/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Enterprise apps" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Enterprise apps </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Get the latest </span> </span> </li> <li class="devsite-nav-item"> <a href="/latest-updates" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Latest updates" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Latest updates </span> </a> </li> <li class="devsite-nav-item"> <a href="/latest-updates/experimental" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Experimental updates" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Experimental updates </span> </a> </li> <li class="devsite-nav-item"> <a href="/studio/preview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Studio preview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Studio preview </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/versions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Jetpack &amp; Compose libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Jetpack &amp; Compose libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/wearables/versions/4" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS preview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS preview </span> </a> </li> <li class="devsite-nav-item"> <a href="/design-for-safety/privacy-sandbox" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Privacy Sandbox" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Privacy Sandbox </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Design &amp; Plan" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > UI Design </span> </span> </li> <li class="devsite-nav-item"> <a href="/design/ui" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Design for Android" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Design for Android </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/mobile" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Mobile" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Mobile </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/large-screens" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Large screens (e.g., tablets)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Large screens (e.g., tablets) </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/widget" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Widgets" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Widgets </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/wear" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/design/ui/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Architecture </span> </span> </li> <li class="devsite-nav-item"> <a href="/topic/architecture/intro" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Introduction" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Introduction </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/libraries/view-binding" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/navigation/navigation-principles" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Navigation" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Navigation </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/modularization" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Modularization" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Modularization </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/testing/fundamentals" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Testing" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Testing </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Quality </span> </span> </li> <li class="devsite-nav-item"> <a href="/quality" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/core-value" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Core value" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Core value </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/user-experience" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: User experience" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > User experience </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/technical" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Technical quality" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Technical quality </span> </a> </li> <li class="devsite-nav-item"> <a href="/quality/privacy-and-security" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Security" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Security </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Security </span> </span> </li> <li class="devsite-nav-item"> <a href="/security" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-and-security/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Privacy" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Privacy </span> </a> </li> <li class="devsite-nav-item"> <a href="/identity" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Identity" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Identity </span> </a> </li> <li class="devsite-nav-item"> <a href="/security/fraud-prevention" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Fraud prevention" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Fraud prevention </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build for Billions </span> </span> </li> <li class="devsite-nav-item"> <a href="/build-for-billions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/quality-guidelines/build-for-billions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: About new markets" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > About new markets </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/androidgo" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android (Go edition)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android (Go edition) </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Develop" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Build AI experiences </span> </span> </li> <li class="devsite-nav-item"> <a href="/ai" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Get started" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Get started </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Core areas </span> </span> </li> <li class="devsite-nav-item"> <a href="/samples" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Samples" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Samples </span> </a> </li> <li class="devsite-nav-item"> <a href="/quick-guides" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Try Quick Guidesᵇᵉᵗᵃ" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Try Quick Guidesᵇᵉᵗᵃ </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/ui" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: User interfaces" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > User interfaces </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/permissions/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Permissions" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Permissions </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop/background-work" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Background work" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Background work </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/data" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Data and files" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Data and files </span> </a> </li> <li class="devsite-nav-item"> <a href="/develop#core-areas" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: All core areas ⤵️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > All core areas ⤵️ </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Tools and workflow </span> </span> </li> <li class="devsite-nav-item"> <a href="/studio/write" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Write and debug code" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Write and debug code </span> </a> </li> <li class="devsite-nav-item"> <a href="/build/gradle-build-overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Build projects" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Build projects </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/testing" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Test your app" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Test your app </span> </a> </li> <li class="devsite-nav-item"> <a href="/topic/performance/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Performance" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Performance </span> </a> </li> <li class="devsite-nav-item"> <a href="/tools" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Command-line tools" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Command-line tools </span> </a> </li> <li class="devsite-nav-item"> <a href="/reference/tools/gradle-api" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Gradle plugin API" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Gradle plugin API </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Device tech </span> </span> </li> <li class="devsite-nav-item"> <a href="/guide/topics/large-screens/get-started-with-large-screens" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Large screens (e.g., tablets)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Large screens (e.g., tablets) </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/wearables" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Wear OS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Wear OS </span> </a> </li> <li class="devsite-nav-item"> <a href="/health-and-fitness/guides" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android Health" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android Health </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide/topics/connectivity/cross-device-sdk/overview" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cross-device SDK" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cross-device SDK </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/cars" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android for Cars" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android for Cars </span> </a> </li> <li class="devsite-nav-item"> <a href="/training/tv" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android TV" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android TV </span> </a> </li> <li class="devsite-nav-item"> <a href="/chrome-os/intro" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: ChromeOS" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > ChromeOS </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > Libraries </span> </span> </li> <li class="devsite-nav-item"> <a href="/reference/packages" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Android platform" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Android platform </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/explorer" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Jetpack libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Jetpack libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="/jetpack/androidx/releases/compose" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Compose libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Compose libraries </span> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/android/reference/packages" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play services ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play services ↗️ </span> </a> </li> <li class="devsite-nav-item"> <a href="https://play.google.com/sdks" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Play SDK index ↗️" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Play SDK index ↗️ </span> </a> </li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" has-book-nav has-sidebar > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars ></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://developer.android.com/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Android Developers" > Android Developers </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/get-started/overview" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Get started" > Get started </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/jetpack" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="Jetpack" > Jetpack </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developer.android.com/jetpack/androidx/explorer" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="4" track-type="globalNav" track-name="breadcrumb" track-metadata-position="4" track-metadata-eventdetail="" > Libraries </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <devsite-recommendations-dropdown class="nocontent"></devsite-recommendations-dropdown> <div class="devsite-article-body clearfix devsite-no-page-title"> <h1 class="devsite-page-title" style="width:50%" id="media3" data-text="Media3" tabindex="-1">Media3</h1> <div style="align:right; text-align:right; padding-bottom:21px; margin-top:-45px; border-bottom:1px solid black;"> &nbsp;&nbsp;<a href="https://github.com/androidx/media/tree/main/demos">Code Sample</a> </div> <div style="float:left; font-size:medium; margin-bottom:5px; margin-top:10px" class="nocontent"> <div style="text-align:left; font-size:90%; padding-right:30px; margin-right:10px; margin-bottom:10px;"> API Reference<br> <a href="/reference/kotlin/androidx/media3/common/package-summary">androidx.media3.common</a><br> </div> </div> <div style="text-align:left; padding-left:10px; margin-left:10px; margin-top:15px; margin-bottom:10px;"> Support libraries for media use cases. </div> <div style="clear:both"></div> <table style="width:100%"> <tr> <th style="width:15%">Latest Update</th> <th style="width:15%">Stable Release</th> <th style="width:15%">Release Candidate</th> <th style="width:15%">Beta Release</th> <th style="width:15%">Alpha Release</th></tr> <tr> <td>November 13, 2024</td> <td><a href="/jetpack/androidx/releases/media3#1.4.1">1.4.1</a></td> <td><a href="/jetpack/androidx/releases/media3#1.5.0-rc01">1.5.0-rc01</a></td> <td>-</td> <td>-</td> </tr> </table> <h2 id="declaring_dependencies" data-text="Declaring dependencies" tabindex="-1">Declaring dependencies</h2> <p>To add a dependency on Media3, you must add the Google Maven repository to your project. Read <a href="/studio/build/dependencies#google-maven">Google&#39;s Maven repository</a> for more information.</p> <p>Add the dependencies for the artifacts you need in the <code translate="no" dir="ltr">build.gradle</code> file for your app or module:</p> <div> <div class="ds-selector-tabs"><section><h3 id="groovy" data-text="Groovy" tabindex="-1">Groovy</h3> <pre class="prettyprint lang-groovy" translate="no" dir="ltr"> dependencies { def media3_version = "1.4.1" // For media playback using ExoPlayer implementation "androidx.media3:media3-exoplayer:$media3_version" // For DASH playback support with ExoPlayer implementation "androidx.media3:media3-exoplayer-dash:$media3_version" // For HLS playback support with ExoPlayer implementation "androidx.media3:media3-exoplayer-hls:$media3_version" // For SmoothStreaming playback support with ExoPlayer implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version" // For RTSP playback support with ExoPlayer implementation "androidx.media3:media3-exoplayer-rtsp:$media3_version" // For MIDI playback support with ExoPlayer (see additional dependency requirements in // https://github.com/androidx/media/blob/release/libraries/decoder_midi/README.md) implementation "androidx.media3:media3-exoplayer-midi:$media3_version" // For ad insertion using the Interactive Media Ads SDK with ExoPlayer implementation "androidx.media3:media3-exoplayer-ima:$media3_version" // For loading data using the Cronet network stack implementation "androidx.media3:media3-datasource-cronet:$media3_version" // For loading data using the OkHttp network stack implementation "androidx.media3:media3-datasource-okhttp:$media3_version" // For loading data using librtmp implementation "androidx.media3:media3-datasource-rtmp:$media3_version" // For building media playback UIs implementation "androidx.media3:media3-ui:$media3_version" // For building media playback UIs for Android TV using the Jetpack Leanback library implementation "androidx.media3:media3-ui-leanback:$media3_version" // For exposing and controlling media sessions implementation "androidx.media3:media3-session:$media3_version" // For extracting data from media containers implementation "androidx.media3:media3-extractor:$media3_version" // For integrating with Cast implementation "androidx.media3:media3-cast:$media3_version" // For scheduling background operations using Jetpack Work's WorkManager with ExoPlayer implementation "androidx.media3:media3-exoplayer-workmanager:$media3_version" // For transforming media files implementation "androidx.media3:media3-transformer:$media3_version" // For applying effects on video frames implementation "androidx.media3:media3-effect:$media3_version" // For muxing media files implementation "androidx.media3:media3-muxer:$media3_version" // Utilities for testing media components (including ExoPlayer components) implementation "androidx.media3:media3-test-utils:$media3_version" // Utilities for testing media components (including ExoPlayer components) via Robolectric implementation "androidx.media3:media3-test-utils-robolectric:$media3_version" // Common functionality for reading and writing media containers implementation "androidx.media3:media3-container:$media3_version" // Common functionality for media database components implementation "androidx.media3:media3-database:$media3_version" // Common functionality for media decoders implementation "androidx.media3:media3-decoder:$media3_version" // Common functionality for loading data implementation "androidx.media3:media3-datasource:$media3_version" // Common functionality used across multiple media libraries implementation "androidx.media3:media3-common:$media3_version" // Common Kotlin-specific functionality implementation "androidx.media3:media3-common-ktx:$media3_version" }</pre> </section><section><h3 id="kts" data-text="Kotlin" tabindex="-1">Kotlin</h3> <pre class="prettyprint lang-kotlin" translate="no" dir="ltr"> dependencies { val media3_version = "1.4.1" // For media playback using ExoPlayer implementation("androidx.media3:media3-exoplayer:$media3_version") // For DASH playback support with ExoPlayer implementation("androidx.media3:media3-exoplayer-dash:$media3_version") // For HLS playback support with ExoPlayer implementation("androidx.media3:media3-exoplayer-hls:$media3_version") // For SmoothStreaming playback support with ExoPlayer implementation("androidx.media3:media3-exoplayer-smoothstreaming:$media3_version") // For RTSP playback support with ExoPlayer implementation("androidx.media3:media3-exoplayer-rtsp:$media3_version") // For MIDI playback support with ExoPlayer (see additional dependency requirements in // https://github.com/androidx/media/blob/release/libraries/decoder_midi/README.md) implementation("androidx.media3:media3-exoplayer-midi:$media3_version") // For ad insertion using the Interactive Media Ads SDK with ExoPlayer implementation("androidx.media3:media3-exoplayer-ima:$media3_version") // For loading data using the Cronet network stack implementation("androidx.media3:media3-datasource-cronet:$media3_version") // For loading data using the OkHttp network stack implementation("androidx.media3:media3-datasource-okhttp:$media3_version") // For loading data using librtmp implementation("androidx.media3:media3-datasource-rtmp:$media3_version") // For building media playback UIs implementation("androidx.media3:media3-ui:$media3_version") // For building media playback UIs for Android TV using the Jetpack Leanback library implementation("androidx.media3:media3-ui-leanback:$media3_version") // For exposing and controlling media sessions implementation("androidx.media3:media3-session:$media3_version") // For extracting data from media containers implementation("androidx.media3:media3-extractor:$media3_version") // For integrating with Cast implementation("androidx.media3:media3-cast:$media3_version") // For scheduling background operations using Jetpack Work's WorkManager with ExoPlayer implementation("androidx.media3:media3-exoplayer-workmanager:$media3_version") // For transforming media files implementation("androidx.media3:media3-transformer:$media3_version") // For applying effects on video frames implementation("androidx.media3:media3-effect:$media3_version") // For muxing media files implementation("androidx.media3:media3-muxer:$media3_version") // Utilities for testing media components (including ExoPlayer components) implementation("androidx.media3:media3-test-utils:$media3_version") // Utilities for testing media components (including ExoPlayer components) via Robolectric implementation("androidx.media3:media3-test-utils-robolectric:$media3_version") // Common functionality for reading and writing media containers implementation("androidx.media3:media3-container:$media3_version") // Common functionality for media database components implementation("androidx.media3:media3-database:$media3_version") // Common functionality for media decoders implementation("androidx.media3:media3-decoder:$media3_version") // Common functionality for loading data implementation("androidx.media3:media3-datasource:$media3_version") // Common functionality used across multiple media libraries implementation("androidx.media3:media3-common:$media3_version") // Common Kotlin-specific functionality implementation("androidx.media3:media3-common-ktx:$media3_version") }</pre> </section></div> </div> <p>For more information about dependencies, see <a href="/studio/build/dependencies">Add Build Dependencies</a>.</p> <h2 id="feedback" data-text="Feedback" tabindex="-1">Feedback</h2> <p>Your feedback helps make Jetpack better. You can use the <a href="https://github.com/androidx/media/issues">Media3 issue tracker</a> to find answers to questions, known issues and feature requests, and to file new issues.</p> <h2 id="version_15_2" data-text="Version 1.5" tabindex="-1">Version 1.5</h2> <h3 id="1.5.0-rc02" data-text="1.5.0-rc02 (2024-11-19)" tabindex="-1">1.5.0-rc02 (2024-11-19)</h3> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.5.0-rc02</code> is released.</p> <p>Version 1.5.0-rc02 contains <a href="https://github.com/androidx/media/commits/1.5.0-rc02">these commits</a>.</p> <p>This release includes the following changes since the <a href="#1.5.0-rc01">1.5.0-rc01 release</a>:</p> <ul> <li>Extractors: <ul> <li>Add AC-4 Level-4 ISO base media file format support (<a href="https://github.com/androidx/media/pull/1265">#1265</a>).</li> </ul></li> <li>Text: <ul> <li>Fix garbled CEA-608 subtitles in content with more than one SEI message per sample.</li> <li>Fix playback hanging on DASH multi-period streams when CEA-608 subtitles are enabled (<a href="https://github.com/androidx/media/issues/1863">#1863</a>).</li> <li>Fix garbled CEA-608 subtitles in MP4 files that incorrectly mark every sample as a sync sample (<a href="https://github.com/androidx/media/issues/1863">#1863</a>).</li> </ul></li> <li>Demo app <ul> <li>Resolve the memory leaks in demo short-form app (<a href="https://github.com/androidx/media/issues/1839">#1839</a>).</li> </ul></li> </ul> <h3 id="1.5.0-rc01" data-text="1.5.0-rc01 (2024-11-13)" tabindex="-1">1.5.0-rc01 (2024-11-13)</h3> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.5.0-rc01</code> is released.</p> <p>Version 1.5.0-rc01 contains <a href="https://github.com/androidx/media/commits/1.5.0-rc01">these commits</a>.</p> <p>This release includes the following changes since the <a href="#1.5.0-beta01">1.5.0-beta01 release</a>:</p> <ul> <li>ExoPlayer: <ul> <li>Fix bug where playlist items or periods in multi-period DASH streams with durations that don&#39;t match the actual content could cause frame freezes at the end of the item (<a href="https://github.com/androidx/media/issues/1698">#1698</a>).</li> <li>Add a setter to <code translate="no" dir="ltr">SntpClient</code> to set the max elapsed time since the last update after which the client is re-initialized (<a href="https://github.com/androidx/media/pull/1794">#1794</a>).</li> </ul></li> <li>Extractors: <ul> <li>Fix media duration parsing in <code translate="no" dir="ltr">mdhd</code> box of MP4 files to handle <code translate="no" dir="ltr">-1</code> values (<a href="https://github.com/androidx/media/issues/1819">#1819</a>).</li> <li>Add support for identifying <code translate="no" dir="ltr">h263</code> box in MP4 files for H.263 video (<a href="https://github.com/androidx/media/issues/1821">#1821</a>).</li> </ul></li> <li>DataSource: <ul> <li><code translate="no" dir="ltr">DataSourceContractTest</code>: Assert that <code translate="no" dir="ltr">DataSource.getUri()</code> returns the resolved URI (as documented). Where this is different to the requested URI, tests can indicate this using the new <code translate="no" dir="ltr">DataSourceContractTest.TestResource.Builder.setResolvedUri()</code> method.</li> <li><code translate="no" dir="ltr">DataSourceContractTest</code>: Assert that <code translate="no" dir="ltr">DataSource.getUri()</code> and <code translate="no" dir="ltr">getResponseHeaders()</code> return their &#39;open&#39; value after a failed call to <code translate="no" dir="ltr">open()</code> (due to a &#39;not found&#39; resource) and before a subsequent <code translate="no" dir="ltr">close()</code> call. <ul> <li>Overriding <code translate="no" dir="ltr">DataSourceContractTest.getNotFoundResources()</code> allows test sub-classes to provide multiple &#39;not found&#39; resources, and to provide any expected headers too. This allows to distinguish between HTTP 404 (with headers) and &quot;server not found&quot; (no headers).</li> </ul></li> </ul></li> <li>Text: <ul> <li>Fix CEA-608 subtitles in H.264 MPEG-TS streams not being output (this was broken in <code translate="no" dir="ltr">1.5.0-alpha01</code> by https://github.com/androidx/media/commit/03a205f220ecf7681f85f8a752227e3986e257ff).</li> <li>Support CEA-608 subtitles in Dolby Vision content (<a href="https://github.com/androidx/media/issues/1820">#1820</a>).</li> </ul></li> <li>RTSP Extension: <ul> <li>Fix crashing when parsing of RTP packets with header extensions (<a href="https://github.com/androidx/media/pull/1225">#1225</a>).</li> </ul></li> </ul> <h3 id="1.5.0-beta01" data-text="Version 1.5.0-beta01" tabindex="-1">Version 1.5.0-beta01</h3> <p>October 30, 2024</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.5.0-beta01</code> is released. Version 1.5.0-beta01 contains <a href="https://github.com/androidx/media/commits/1.5.0-beta01">these commits</a>.</p> <ul> <li>Common Library: <ul> <li>Remove <code translate="no" dir="ltr">@DoNotInline</code> annotations from manually out-of-lined inner classes designed to avoid <a href="https://chromium.googlesource.com/chromium/src/+/HEAD/build/android/docs/class_verification_failures.md">runtime class verification failures</a>. Recent versions of <a href="https://developer.android.com/build/shrink-code">R8</a> now automatically out-of-line calls like these to avoid the runtime failures (so the manual out-of-lining is no longer required). All Gradle users of the library must already be a using a version of the Android Gradle Plugin that uses a version of R8 which does this, <a href="https://issuetracker.google.com/345472586#comment7">due to <code translate="no" dir="ltr">compileSdk = 35</code></a>. Users of the library with non-Gradle build systems will need to ensure their R8-equivalent shrinking/obfuscating step does a similar automatic out-of-lining process in order to avoid runtime class verification failures. This change has <a href="http://r.android.com/3156141">already been done in other AndroidX libraries</a>.</li> </ul></li> <li>ExoPlayer: <ul> <li>Fix <code translate="no" dir="ltr">MediaCodec.CryptoException</code> sometimes being reported as an &quot;unexpected runtime error&quot; when <code translate="no" dir="ltr">MediaCodec</code> is operated in asynchronous mode (default behaviour on API 31+).</li> <li>Pass <code translate="no" dir="ltr">bufferedDurationUs</code> instead of <code translate="no" dir="ltr">bufferedPositionUs</code> with <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl.onContinueLoadingRequested()</code>. Also changes <code translate="no" dir="ltr">DefaultPreloadManager.Status.STAGE_LOADED_TO_POSITION_MS</code> to <code translate="no" dir="ltr">DefaultPreloadManager.Status.STAGE_LOADED_FOR_DURATION_MS</code>, apps then need to pass a value representing a specific duration from the default start position for which the corresponding media source has to be preloaded with this IntDef, instead of a position.</li> <li>Add <code translate="no" dir="ltr">ForwardingRenderer</code> implementation that forwards all method calls to another renderer (<a href="https://github.com/androidx/media/pull/1703">1703</a>).</li> <li>Add playlist preloading for the next item in the playlist. Apps can enable preloading by calling <code translate="no" dir="ltr">ExoPlayer.setPreloadConfiguration(PreloadConfiguration)</code> accordingly. By default preloading is disabled. When opted-in and to not interfere with playback, <code translate="no" dir="ltr">DefaultLoadControl</code> restricts preloading to start and continue only when the player is not loading for playback. Apps can change this behaviour by implementing <code translate="no" dir="ltr">LoadControl.shouldContinuePreloading()</code> accordingly (like when overriding this method in <code translate="no" dir="ltr">DefaultLoadControl</code>). The default implementation of <code translate="no" dir="ltr">LoadControl</code> disables preloading in case an app is using a custom implementation of <code translate="no" dir="ltr">LoadControl</code>.</li> <li>Add method <code translate="no" dir="ltr">MediaSourceEventListener.EventDispatcher.dispatchEvent()</code> to allow invoking events of subclass listeners (<a href="https://github.com/androidx/media/pull/1736">1736</a>).</li> <li>Add <code translate="no" dir="ltr">DefaultPreloadManager.Builder</code> that builds the <code translate="no" dir="ltr">DefaultPreloadManager</code> and <code translate="no" dir="ltr">ExoPlayer</code> instances with consistently shared configurations.</li> <li>Remove <code translate="no" dir="ltr">Renderer[]</code> parameter from <code translate="no" dir="ltr">LoadControl.onTracksSelected()</code> as <code translate="no" dir="ltr">DefaultLoadControl</code> implementation can retrieve the stream types from <code translate="no" dir="ltr">ExoTrackSelection[]</code>.</li> <li>Deprecated <code translate="no" dir="ltr">DefaultLoadControl.calculateTargetBufferBytes(Renderer[], ExoTrackSelection[])</code> and marked method as final to prevent overrides. The new <code translate="no" dir="ltr">DefaultLoadControl.calculateTargetBufferBytes(ExoTrackSelection[])</code> should be used instead.</li> <li>Report <code translate="no" dir="ltr">MediaSourceEventListener</code> events from secondary sources in <code translate="no" dir="ltr">MergingMediaSource</code>. This will result in load start/error/cancelled/completed events being reported for sideloaded subtitles (those added with <code translate="no" dir="ltr">MediaItem.LocalConfiguration.subtitleConfigurations</code>), which may appear as duplicate load events emitted from <code translate="no" dir="ltr">AnalyticsListener</code>.</li> <li>Prevent subtitle &amp; metadata errors from completely stopping playback. Instead the problematic track is disabled and playback of the remaining tracks continues (<a href="https://github.com/google/ExoPlayer/issues/1722">#1722</a>). <ul> <li>In new subtitle handling (during extraction), associated parse (e.g. invalid subtitle data) and load errors (e.g. HTTP 404) are emitted via <code translate="no" dir="ltr">onLoadError</code> callbacks.</li> <li>In legacy subtitle handling (during rendering), only associated load errors are emitted via <code translate="no" dir="ltr">onLoadError</code> callbacks while parse errors are silently ignored (this is pre-existing behaviour).</li> </ul></li> </ul></li> <li>Transformer: <ul> <li>Make setting the image duration using <code translate="no" dir="ltr">MediaItem.Builder.setImageDurationMs</code> mandatory for image export.</li> <li>Add export support for gaps in sequences of audio EditedMediaItems.</li> </ul></li> <li>Track Selection: <ul> <li><code translate="no" dir="ltr">DefaultTrackSelector</code>: Prefer object-based audio over channel-based audio when other factors are equal.</li> </ul></li> <li>Extractors: <ul> <li>Fix preroll sample handling for non-keyframe media start positions when processing edit lists in MP4 files (<a href="https://github.com/google/ExoPlayer/issues/1659">#1659</a>).</li> <li>Improved frame rate calculation by using media duration from the <code translate="no" dir="ltr">mdhd</code> box in <code translate="no" dir="ltr">Mp4Extractor</code> and <code translate="no" dir="ltr">FragmentedMp4Extractor</code> (<a href="https://github.com/androidx/media/issues/1531">#1531</a>).</li> <li>Fix incorrect scaling of <code translate="no" dir="ltr">media_time</code> in MP4 edit lists. While <code translate="no" dir="ltr">segment_duration</code> was already correctly scaled using the movie timescale, <code translate="no" dir="ltr">media_time</code> is now properly scaled using the track timescale, as specified by the MP4 format standard (<a href="https://github.com/androidx/media/issues/1792">#1792</a>).</li> <li>Handle out-of-order frames in <code translate="no" dir="ltr">endIndices</code> calculation for MP4 with edit list (<a href="https://github.com/androidx/media/issues/1797">#1797</a>).</li> </ul></li> <li>Audio: <ul> <li>Fix pop sounds that may occur during seeks.</li> <li>Fix truncation error accumulation for Sonic&#39;s time-stretching/pitch-shifting algorithm.</li> <li>Fix bug in <code translate="no" dir="ltr">SpeedChangingAudioProcessor</code> that causes dropped output frames.</li> </ul></li> <li>Video: <ul> <li>Add workaround for a device issue on Galaxy Tab S7 FE that causes 60fps secure H264 streams to be marked as unsupported (<a href="https://github.com/androidx/media/issues/1619">#1619</a>).</li> <li>Add workaround for codecs that get stuck after the last sample without returning an end-of-stream signal.</li> </ul></li> <li>Text: <ul> <li>Ensure WebVTT in HLS with very large subtitle timestamps (which overflow a 64-bit <code translate="no" dir="ltr">long</code> when represented as microseconds and multiplied by the <code translate="no" dir="ltr">90,000</code> MPEG timebase) are displayed (<a href="https://github.com/androidx/media/issues/1763">#1763</a>).</li> </ul></li> <li>Metadata: <ul> <li>Assign the <code translate="no" dir="ltr">C.TRACK_TYPE_METADATA</code> type to tracks containing icy or vnd.dvb.ait content.</li> </ul></li> <li>DRM: <ul> <li>Fix <code translate="no" dir="ltr">IllegalStateException</code> from <code translate="no" dir="ltr">DefaultDrmSession.requiresSecureDecoder</code> after opening a DRM session failed. This issue was introduced in <code translate="no" dir="ltr">1.5.0-alpha01</code>.</li> </ul></li> <li>Muxers:</li> <li>IMA extension: <ul> <li>Fix bug where server-side inserted DAI streams without a preroll can result in an <code translate="no" dir="ltr">ArrayIndexOutOfBoundsException</code> when playing past the last midroll (<a href="https://github.com/androidx/media/issues/1741">#1741</a>).</li> </ul></li> <li>Session: <ul> <li>Fix bug that caused custom commands sent from a <code translate="no" dir="ltr">MediaBrowser</code> being dispatched to the <code translate="no" dir="ltr">MediaSessionCompat.Callback</code> instead of the <code translate="no" dir="ltr">MediaBrowserServiceCompat</code> variant of the method when connected to a legacy service. This prevented the <code translate="no" dir="ltr">MediaBrowser</code> to receive the actual return value sent back by the legacy service (<a href="https://github.com/androidx/media/issues/1474">#1474</a>).</li> <li>Handle <code translate="no" dir="ltr">IllegalArgumentException</code> thrown by devices of certain manufacturers when setting the broadcast receiver for media button intents (<a href="https://github.com/androidx/media/issues/1730">#1730</a>).</li> <li>Add command buttons for media items. This adds the Media3 API for what was known as <code translate="no" dir="ltr">Custom browse actions</code> with the legacy library with <code translate="no" dir="ltr">MediaBrowserCompat</code>. Note that with Media3 command buttons for media items are available for both, <code translate="no" dir="ltr">MediaBrowser</code> and <code translate="no" dir="ltr">MediaController</code>. See <a href="https://developer.android.com/training/cars/media#custom_browse_actions">Custom Browse actions of AAOS</a>.</li> <li>Fix bug where a Media3 controller was sometimes unable to let a session app start a foreground service after requesting <code translate="no" dir="ltr">play()</code>.</li> <li>Restrict <code translate="no" dir="ltr">CommandButton.Builder.setIconUri</code> to only accept content Uris.</li> <li>Pass connection hints of a Media3 browser to the initial <code translate="no" dir="ltr">MediaBrowserCompat</code> when connecting to a legacy <code translate="no" dir="ltr">MediaBrowserCompat</code>. The service can receive the connection hints passed in as root hints with the first call to <code translate="no" dir="ltr">onGetRoot()</code>.</li> <li>Fix bug where a <code translate="no" dir="ltr">MediaBrowser</code> connected to a legacy browser service, didn&#39;t receive an error sent by the service after the browser has subscribed to a <code translate="no" dir="ltr">parentid</code>.</li> <li>Improve interoperability behavior, so that a Media3 browser that is connected to a legacy <code translate="no" dir="ltr">MediaBrowserService</code> doesn&#39;t request the children of a <code translate="no" dir="ltr">parentId</code> twice when subscribing to a parent.</li> </ul></li> <li>UI: <ul> <li>Make the stretched/cropped video in <code translate="no" dir="ltr">PlayerView</code>-in-Compose-<code translate="no" dir="ltr">AndroidView</code> workaround opt-in, due to issues with XML-based shared transitions. Apps using <code translate="no" dir="ltr">PlayerView</code> inside <code translate="no" dir="ltr">AndroidView</code> need to call <code translate="no" dir="ltr">PlayerView.setEnableComposeSurfaceSyncWorkaround</code> in order to opt-in (<a href="https://github.com/androidx/media/issues/1237">#1237</a>, <a href="https://github.com/androidx/media/issues/1594">#1594</a>).</li> <li>Add <code translate="no" dir="ltr">setFullscreenButtonState</code> to <code translate="no" dir="ltr">PlayerView</code> to allow updates of fullscreen button&#39;s icon on demand, i.e. out-of-band and not reactively to a click interaction (<a href="https://github.com/androidx/media/issues/1590">#1590</a>, <a href="https://github.com/androidx/media/issues/184">#184</a>).</li> <li>Fix bug where the &quot;None&quot; choice in the text selection is not working if there are app-defined text track selection preferences.</li> </ul></li> <li>Smooth Streaming Extension: <ul> <li>Fix a <code translate="no" dir="ltr">Bad magic number for Bundle</code> error when playing SmoothStreaming streams with text tracks (<a href="https://github.com/androidx/media/issues/1779">#1779</a>).</li> </ul></li> <li>RTSP Extension: <ul> <li>Fix user info removal for URLs that contain encoded @ characters (<a href="https://github.com/androidx/media/pull/1138">#1138</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, etc.): <ul> <li>Add 16 KB page support for decoder extensions on Android 15 (<a href="https://github.com/androidx/media/issues/1685">#1685</a>).</li> </ul></li> <li>Cast Extension: <ul> <li>Stop cleaning the timeline after the CastSession disconnects, which enables the sender app to resume playback locally after a disconnection.</li> <li>Populate CastPlayer&#39;s <code translate="no" dir="ltr">DeviceInfo</code> when a <code translate="no" dir="ltr">Context</code> is provided. This enables linking the <code translate="no" dir="ltr">MediaSession</code> to a <code translate="no" dir="ltr">RoutingSession</code>, which is necessary for integrating Output Switcher (<a href="https://github.com/androidx/media/issues/1056">#1056</a>).</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove deprecated <code translate="no" dir="ltr">DefaultEncoderFactory</code> constructors. Use <code translate="no" dir="ltr">DefaultEncoderFactory.Builder</code> instead.</li> </ul></li> </ul> <h3 id="1.5.0-alpha01" data-text="Version 1.5.0-alpha01" tabindex="-1">Version 1.5.0-alpha01</h3> <p>September 10, 2024</p> <p>This release includes the following changes since the <a href="#1.4.1">1.4.1 release</a>:</p> <ul> <li>Common Library: <ul> <li>Add <code translate="no" dir="ltr">ForwardingSimpleBasePlayer</code> that allows forwarding to another player with small adjustments while ensuring full consistency and listener handling (<a href="https://github.com/androidx/media/issues/1183">#1183</a>).</li> <li>Replace <code translate="no" dir="ltr">SimpleBasePlayer.State.playlist</code> by <code translate="no" dir="ltr">getPlaylist()</code> method.</li> <li>Add override for <code translate="no" dir="ltr">SimpleBasePlayer.State.Builder.setPlaylist()</code> to directly specify a <code translate="no" dir="ltr">Timeline</code> and current <code translate="no" dir="ltr">Tracks</code> and <code translate="no" dir="ltr">Metadata</code> instead of building a playlist structure.</li> <li>Increase <code translate="no" dir="ltr">minSdk</code> to 21 (Android Lollipop). This is aligned with all other AndroidX libraries.</li> <li>Add <code translate="no" dir="ltr">androidx.media3:media3-common-ktx</code> artifact which provides Kotlin-specific functionality built on top of the Common library</li> <li>Add <code translate="no" dir="ltr">Player.listen</code> suspending extension function to spin a coroutine to listen to <code translate="no" dir="ltr">Player.Events</code> to the <code translate="no" dir="ltr">media3-common-ktx</code> library.</li> </ul></li> <li>ExoPlayer: <ul> <li><code translate="no" dir="ltr">MediaCodecRenderer.onProcessedStreamChange()</code> can now be called for every media item. Previously it was not called for the first one. Use <code translate="no" dir="ltr">MediaCodecRenderer.experimentalEnableProcessedStreamChangedAtStart()</code> to enable this.</li> <li>Add <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl.onPreloadError</code> to allow <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl</code> implementations to take actions when error occurs.</li> <li>Add <code translate="no" dir="ltr">BasePreloadManager.Listener</code> to propagate preload events to apps.</li> <li>Allow changing SNTP client timeout and retry alternative addresses on timeout (<a href="https://github.com/androidx/media/issues/1540">#1540</a>).</li> <li>Remove <code translate="no" dir="ltr">MediaCodecAdapter.Configuration.flags</code> as the field was always zero.</li> <li>Allow the user to select the built-in speaker for playback on Wear OS API 35+ (where the device advertises support for this).</li> <li>Defer the blocking call to <code translate="no" dir="ltr">Context.getSystemService(Context.AUDIO_SERVICE)</code> until audio focus handling is enabled. This ensures the blocking call isn&#39;t done if audio focus handling is not enabled (<a href="https://github.com/androidx/media/pull/1616">#1616</a>).</li> <li>Allow playback regardless of buffered duration when loading fails (<a href="https://github.com/androidx/media/issues/1571">#1571</a>).</li> <li>Add <code translate="no" dir="ltr">AnalyticsListener.onRendererReadyChanged()</code> to signal when individual renderers allow playback to be ready.</li> </ul></li> <li>Transformer: <ul> <li>Add <code translate="no" dir="ltr">SurfaceAssetLoader</code>, which supports queueing video data to Transformer via a <code translate="no" dir="ltr">Surface</code>.</li> <li><code translate="no" dir="ltr">ImageAssetLoader</code> reports unsupported input via <code translate="no" dir="ltr">AssetLoader.onError</code> instead of throwing an <code translate="no" dir="ltr">IllegalStateException</code>.</li> </ul></li> <li>Extractors: <ul> <li>Allow <code translate="no" dir="ltr">Mp4Extractor</code> and <code translate="no" dir="ltr">FragmentedMp4Extractor</code> to identify H264 samples that are not used as reference by subsequent samples.</li> <li>Add option to enable index-based seeking in <code translate="no" dir="ltr">AmrExtractor</code>.</li> <li>Treat MP3 files with more than 128kB between valid frames as truncated (instead of invalid). This means files with non-MP3 data at the end, with no other metadata to indicate the length of the MP3 bytes, now stop playback at the end of the MP3 data instead of failing with <code translate="no" dir="ltr">ParserException: Searched too many bytes.{contentIsMalformed=true, dataType=1}</code> (<a href="https://github.com/androidx/media/issues/1563">#1563</a>).</li> </ul></li> <li>DataSource: <ul> <li>Update <code translate="no" dir="ltr">HttpEngineDataSource</code> to allow use starting at version S extension 7 instead of API level 34 (<a href="https://github.com/androidx/media/issues/1262">#1262</a>).</li> </ul></li> <li>Audio: <ul> <li>Automatically configure CTA-2075 loudness metadata on the codec if present in the media.</li> <li>Ensure smooth volume ramp down when seeking.</li> </ul></li> <li>Video: <ul> <li><code translate="no" dir="ltr">MediaCodecVideoRenderer</code> avoids decoding samples that are neither rendered nor used as reference by other samples.</li> <li>On API 35 and above, <code translate="no" dir="ltr">MediaCodecAdapter</code> may now receive a <code translate="no" dir="ltr">null</code> <code translate="no" dir="ltr">Surface</code> in <code translate="no" dir="ltr">configure</code> and calls to a new method <code translate="no" dir="ltr">detachOutputSurface</code> to remove a previously set <code translate="no" dir="ltr">Surface</code> if the codec supports this (<code translate="no" dir="ltr">MediaCodecInfo.detachedSurfaceSupported</code>).</li> <li>Use <code translate="no" dir="ltr">MediaCodecAdapter</code> supplied pixel aspect ratio values if provided when processing <code translate="no" dir="ltr">onOutputFormatChanged</code> (<a href="https://github.com/androidx/media/pull/1371">#1371</a>).</li> </ul></li> <li>Text: <ul> <li>Add a custom <code translate="no" dir="ltr">VoiceSpan</code> and populate it for <a href="https://www.w3.org/TR/webvtt1/#webvtt-cue-voice-span">WebVTT voice spans</a> (<a href="https://github.com/androidx/media/issues/1632">#1632</a>).</li> </ul></li> <li>Image: <ul> <li>Add <code translate="no" dir="ltr">ExternallyLoadedImageDecoder</code> for simplified integration with external image loading libraries like Glide or Coil.</li> </ul></li> <li>DataSource: <ul> <li>Add <code translate="no" dir="ltr">FileDescriptorDataSource</code>, a new <code translate="no" dir="ltr">DataSource</code> that can be used to read from a <code translate="no" dir="ltr">FileDescriptor</code> (<a href="https://github.com/google/ExoPlayer/issues/3757">#3757</a>).</li> </ul></li> <li>Effect: <ul> <li>Add <code translate="no" dir="ltr">DefaultVideoFrameProcessor</code> workaround for minor <code translate="no" dir="ltr">SurfaceTexture</code> scaling. <code translate="no" dir="ltr">SurfaceTexture</code> may include a small scaling that cuts off a 1-texel border around the edge of a cropped buffer. This is now handled such that output is closer to expected.</li> <li>Speed up <code translate="no" dir="ltr">DefaultVideoFrameProcessor.queueInputBitmap()</code>. As a result, exporting images to videos with <code translate="no" dir="ltr">Transformer</code> is faster.</li> </ul></li> <li>IMA extension: <ul> <li>Fix bug where clearing the playlist may cause an <code translate="no" dir="ltr">ArrayIndexOutOfBoundsException</code> in <code translate="no" dir="ltr">ImaServerSideAdInsertionMediaSource</code>.</li> </ul></li> <li>Session: <ul> <li>Add <code translate="no" dir="ltr">MediaButtonReceiver.shouldStartForegroundService(Intent)</code> to allow apps to suppress a play command coming in for playback resumption by overriding this method. By default, the service is always started and playback can&#39;t be suppressed without the system crashing the service with a <code translate="no" dir="ltr">ForegroundServiceDidNotStartInTimeException</code> (<a href="https://github.com/google/ExoPlayer/issues/1528">#1528</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Add support for periods starting in the middle of a segment (<a href="https://github.com/androidx/media/issues/1440">#1440</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, etc.): <ul> <li>Add the IAMF decoder module, which provides support for playback of MP4 files containing IAMF tracks using the libiamf native library to synthesize audio. <ul> <li>Playback is enabled with a stereo layout as well as 5.1 with spatialization together with optional head tracking enabled, but binaural playback support is currently not available.</li> </ul></li> </ul></li> <li>Cast Extension: <ul> <li>Stop clearning the timeline after the CastSession disconnects, which enables the sender app to resume playback locally after a disconnection.</li> <li>Populate CastPlayer&#39;s <code translate="no" dir="ltr">DeviceInfo</code> when a <code translate="no" dir="ltr">Context</code> is provided. This enables linking the <code translate="no" dir="ltr">MediaSession</code> to a <code translate="no" dir="ltr">RoutingSession</code>, which is necessary for integrating Output Switcher (<a href="https://github.com/androidx/media/issues/1056">#1056</a>).</li> </ul></li> <li>Test Utilities: <ul> <li><code translate="no" dir="ltr">DataSourceContractTest</code> now includes tests to verify: <ul> <li>Input stream <code translate="no" dir="ltr">read position</code> is updated.</li> <li>Output buffer <code translate="no" dir="ltr">offset</code> is applied correctly.</li> </ul></li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove deprecated <code translate="no" dir="ltr">Player.hasPrevious</code>, <code translate="no" dir="ltr">Player.hasPreviousWindow()</code>. Use <code translate="no" dir="ltr">Player.hasPreviousMediaItem()</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">Player.previous()</code> method. Use <code translate="no" dir="ltr">Player.seekToPreviousMediaItem()</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">DrmSessionEventListener.onDrmSessionAcquired</code> method.</li> </ul></li> </ul> <h2 id="version_140_3" data-text="Version 1.4.0" tabindex="-1">Version 1.4.0</h2> <h3 id="1.4.1" data-text="Version 1.4.1" tabindex="-1">Version 1.4.1</h3> <p>August 27, 2024</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.4.1</code> is released. Version 1.4.1 contains <a href="https://github.com/androidx/media/commits/1.4.1">these commits</a>.</p> <ul> <li>ExoPlayer: <ul> <li>Handle preload callbacks asynchronously in <code translate="no" dir="ltr">PreloadMediaSource</code> (<a href="https://github.com/androidx/media/issues/1568">#1568</a>).</li> <li>Allow playback regardless of buffered duration when loading fails (<a href="https://github.com/androidx/media/issues/1571">#1571</a>).</li> </ul></li> <li>Extractors: <ul> <li>MP3: Fix <code translate="no" dir="ltr">Searched too many bytes</code> error by correctly ignoring trailing non-MP3 data based on the length field in an <code translate="no" dir="ltr">Info</code> frame (<a href="https://github.com/androidx/media/issues/1480">#1480</a>).</li> </ul></li> <li>Text: <ul> <li>TTML: Fix handling of percentage <code translate="no" dir="ltr">tts:fontSize</code> values to ensure they are correctly inherited from parent nodes with percentage <code translate="no" dir="ltr">tts:fontSize</code> values.</li> <li>Fix <code translate="no" dir="ltr">IndexOutOfBoundsException</code> in <code translate="no" dir="ltr">LegacySubtitleUtil</code> due to incorrectly handling the case of the requested output start time being greater than or equal to the final event time in the <code translate="no" dir="ltr">Subtitle</code> (<a href="https://github.com/androidx/media/issues/1516">#1516</a>).</li> </ul></li> <li>DRM: <ul> <li>Fix <code translate="no" dir="ltr">android.media.MediaCodec$CryptoException: Operation not supported in this configuration: ERROR_DRM_CANNOT_HANDLE</code> error on API 31+ devices playing L1 Widevine content. This error is caused by an incomplete implementation of the framework <a href="https://developer.android.com/reference/android/media/MediaDrm#requiresSecureDecoder(java.lang.String)"><code translate="no" dir="ltr">MediaDrm.requiresSecureDecoder</code></a> method (<a href="https://github.com/androidx/media/issues/1603">#1603</a>).</li> </ul></li> <li>Effect: <ul> <li>Add a <code translate="no" dir="ltr">release()</code> method to <code translate="no" dir="ltr">GlObjectsProvider</code>.</li> </ul></li> <li>Session: <ul> <li>Transform a double-tap of <code translate="no" dir="ltr">KEYCODE_HEADSETHOOK</code> into a &#39;seek to next&#39; action, as <a href="https://developer.android.com/reference/androidx/media3/session/MediaSession#media-key-events-mapping">documented</a> (<a href="https://github.com/androidx/media/issues/1493">#1493</a>).</li> <li>Handle <code translate="no" dir="ltr">KEYCODE_HEADSETHOOK</code> as a &#39;play&#39; command in <code translate="no" dir="ltr">MediaButtonReceiver</code> when deciding whether to ignore it to avoid a <code translate="no" dir="ltr">ForegroundServiceDidNotStartInTimeException</code> (<a href="https://github.com/androidx/media/issues/1581">#1581</a>).</li> </ul></li> <li>RTSP Extension: <ul> <li>Skip invalid Media Descriptions in SDP parsing (<a href="https://github.com/androidx/media/issues/1472">#1087</a>).</li> </ul></li> </ul> <h3 id="1.4.0" data-text="Version 1.4.0" tabindex="-1">Version 1.4.0</h3> <p>July 25, 2024</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.4.0</code> is released. Version 1.4.0 contains <a href="https://github.com/androidx/media/commits/1.4.0">these commits</a>.</p> <ul> <li>Common Library: <ul> <li>Forward presumed no-op seek calls to the protected <code translate="no" dir="ltr">BasePlayer.seekTo()</code> and <code translate="no" dir="ltr">SimpleBasePlayer.handleSeek()</code> methods instead of ignoring them. If you are implementing these methods in a custom player, you may need to handle these additional calls with <code translate="no" dir="ltr">mediaItemIndex == C.INDEX_UNSET</code>.</li> <li>Remove compile dependency on enhanced Java 8 desugaring (<a href="https://github.com/androidx/media/issues/1312">#1312</a>).</li> <li>Ensure the duration passed to <code translate="no" dir="ltr">MediaItem.Builder.setImageDurationMs()</code> is ignored for a non-image <code translate="no" dir="ltr">MediaItem</code> (as documented).</li> <li>Add <code translate="no" dir="ltr">Format.customData</code> to store app-provided custom information about <code translate="no" dir="ltr">Format</code> instances.</li> </ul></li> <li>ExoPlayer: <ul> <li>Add <code translate="no" dir="ltr">BasePreloadManager</code> which coordinates the preloading for multiple sources based on the priorities defined by their <code translate="no" dir="ltr">rankingData</code>. Customization is possible by extending this class. Add <code translate="no" dir="ltr">DefaultPreloadManager</code> which uses <code translate="no" dir="ltr">PreloadMediaSource</code> to preload media samples of the sources into memory, and uses an integer <code translate="no" dir="ltr">rankingData</code> that indicates the index of an item on the UI.</li> <li>Add <code translate="no" dir="ltr">PlayerId</code> to most methods of <code translate="no" dir="ltr">LoadControl</code> to enable <code translate="no" dir="ltr">LoadControl</code> implementations to support multiple players.</li> <li>Remove <code translate="no" dir="ltr">Buffer.isDecodeOnly()</code> and <code translate="no" dir="ltr">C.BUFFER_FLAG_DECODE_ONLY</code>. There is no need to set this flag as renderers and decoders will decide to skip buffers based on timestamp. Custom <code translate="no" dir="ltr">Renderer</code> implementations should check if the buffer time is at least <code translate="no" dir="ltr">BaseRenderer.getLastResetPositionUs()</code> to decide whether a sample should be shown. Custom <code translate="no" dir="ltr">SimpleDecoder</code> implementations can check <code translate="no" dir="ltr">isAtLeastOutputStartTimeUs()</code> if needed or mark other buffers with <code translate="no" dir="ltr">DecoderOutputBuffer.shouldBeSkipped</code> to skip them.</li> <li>Allow a null value to be returned by <code translate="no" dir="ltr">TargetPreloadStatusControl.getTargetPreloadStatus(T)</code> to indicate not to preload a <code translate="no" dir="ltr">MediaSource</code> with the given <code translate="no" dir="ltr">rankingData</code>.</li> <li>Add <code translate="no" dir="ltr">remove(MediaSource)</code> to <code translate="no" dir="ltr">BasePreloadManager</code>.</li> <li>Add <code translate="no" dir="ltr">reset()</code> to <code translate="no" dir="ltr">BasePreloadManager</code> to release all the holding sources while keep the preload manager instance.</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.setPriority()</code> (and <code translate="no" dir="ltr">Builder.setPriority()</code>) to define the priority value used in <code translate="no" dir="ltr">PriorityTaskManager</code> and for MediaCodec importance from API 35.</li> <li>Fix issue with updating the last rebuffer time which resulted in incorrect <code translate="no" dir="ltr">bs</code> (buffer starvation) key in CMCD (<a href="https://github.com/androidx/media/issues/1124">#1124</a>).</li> <li>Add <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl.onLoadedToTheEndOfSource(PreloadMediaSource)</code> to indicate that the source has loaded to the end. This allows the <code translate="no" dir="ltr">DefaultPreloadManager</code> and the custom <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl</code> implementations to preload the next source or take other actions.</li> <li>Fix bug where silence skipping at the end of items can trigger a playback exception.</li> <li>Add <code translate="no" dir="ltr">clear</code> to <code translate="no" dir="ltr">PreloadMediaSource</code> to discard the preloading period.</li> <li>Add new error code <code translate="no" dir="ltr">PlaybackException.ERROR_CODE_DECODING_RESOURCES_RECLAIMED</code> that is used when codec resources are reclaimed for higher priority tasks.</li> <li>Let <code translate="no" dir="ltr">AdsMediaSource</code> load preroll ads before initial content media preparation completes (<a href="https://github.com/androidx/media/issues/1358">#1358</a>).</li> <li>Fix bug where playback moved to <code translate="no" dir="ltr">STATE_ENDED</code> when re-preparing a multi-period DASH live stream after the original period was already removed from the manifest.</li> <li>Rename <code translate="no" dir="ltr">onTimelineRefreshed()</code> to <code translate="no" dir="ltr">onSourcePrepared()</code> and <code translate="no" dir="ltr">onPrepared()</code> to <code translate="no" dir="ltr">onTracksSelected()</code> in <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl</code>. Also rename the IntDefs in <code translate="no" dir="ltr">DefaultPreloadManager.Stage</code> accordingly.</li> <li>Add experimental support for dynamic scheduling to better align work with CPU wake-cycles and delay waking up to when renderers can progress. You can enable this using <code translate="no" dir="ltr">experimentalSetDynamicSchedulingEnabled()</code> when setting up your ExoPlayer instance.</li> <li>Add <code translate="no" dir="ltr">Renderer.getDurationToProgressUs()</code>. A <code translate="no" dir="ltr">Renderer</code> can implement this method to return to ExoPlayer the duration that playback must advance for the renderer to progress. If <code translate="no" dir="ltr">ExoPlayer</code> is set with <code translate="no" dir="ltr">experimentalSetDynamicSchedulingEnabled()</code> then <code translate="no" dir="ltr">ExoPlayer</code> will call this method when calculating the time to schedule its work task.</li> <li>Add <code translate="no" dir="ltr">MediaCodecAdapter#OnBufferAvailableListener</code> to alert when input and output buffers are available for use by <code translate="no" dir="ltr">MediaCodecRenderer</code>. <code translate="no" dir="ltr">MediaCodecRenderer</code> will signal <code translate="no" dir="ltr">ExoPlayer</code> when receiving these callbacks and if <code translate="no" dir="ltr">ExoPlayer</code> is set with <code translate="no" dir="ltr">experimentalSetDynamicSchedulingEnabled()</code>, then <code translate="no" dir="ltr">ExoPlayer</code> will schedule its work loop as renderers can make progress.</li> <li>Use data class for <code translate="no" dir="ltr">LoadControl</code> methods instead of individual parameters.</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.isReleased()</code> to check whether <code translate="no" dir="ltr">Exoplayer.release()</code> has been called.</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.Builder.setMaxSeekToPreviousPositionMs()</code> to configure the maximum position for which <code translate="no" dir="ltr">seekToPrevious()</code> seeks to the previous item (<a href="https://github.com/androidx/media/issues/1425">#1425</a>).</li> <li>Fix some audio focus inconsistencies, e.g. not reporting full or transient focus loss while the player is paused (<a href="https://github.com/androidx/media/issues/1436">#1436</a>).</li> <li>Fix potential <code translate="no" dir="ltr">IndexOutOfBoundsException</code> caused by extractors reporting additional tracks after the initial preparation step (<a href="https://github.com/androidx/media/issues/1476">#1476</a>).</li> <li><code translate="no" dir="ltr">Effects</code> in <code translate="no" dir="ltr">ExoPlayer.setVideoEffect()</code> will receive the timestamps with the renderer offset removed (<a href="https://github.com/androidx/media/issues/1098">#1098</a>).</li> <li>Fix potential <code translate="no" dir="ltr">IllegalArgumentException</code> when handling player error that happened while reading ahead into another playlist item (<a href="https://github.com/androidx/media/issues/1483">#1483</a>).</li> </ul></li> <li>Transformer: <ul> <li>Add <code translate="no" dir="ltr">audioConversionProcess</code> and <code translate="no" dir="ltr">videoConversionProcess</code> to <code translate="no" dir="ltr">ExportResult</code> indicating how the respective track in the output file was made.</li> <li>Relax trim optimization H.264 level checks.</li> <li>Add support for changing between SDR and HDR input media in a sequence.</li> <li>Add support for composition-level audio effects.</li> <li>Add support for transcoding Ultra HDR images into HDR videos.</li> <li>Fix issue where the <code translate="no" dir="ltr">DefaultAudioMixer</code> does not output the correct amount of bytes after being reset and reused.</li> <li>Work around a decoder bug where the number of audio channels was capped at stereo when handling PCM input.</li> <li>When selecting tracks in <code translate="no" dir="ltr">ExoPlayerAssetLoader</code>, ignore audio channel count constraints as they only apply for playback.</li> <li>Replace <code translate="no" dir="ltr">androidx.media3.transformer.Muxer</code> interface with <code translate="no" dir="ltr">androidx.media3.muxer.Muxer</code> and remove <code translate="no" dir="ltr">androidx.media3.transformer.Muxer</code>.</li> <li>Fix HEIC image loading from content URI schemes. (<a href="https://github.com/androidx/media/issues/1373">#1373</a>).</li> <li>Adjust audio track duration in <code translate="no" dir="ltr">AudioGraphInput</code> to improve AV sync.</li> <li>Remove <code translate="no" dir="ltr">ExportResult.processedInputs</code> field. If you use this field for codec details, then use <code translate="no" dir="ltr">DefaultDecoderFactory.listener</code> instead. In case of a codec exception, codec details will be available in the <code translate="no" dir="ltr">ExportException.codecInfo</code>.</li> </ul></li> <li>Extractors: <ul> <li>MPEG-TS: Roll forward the change ensuring the last frame is rendered by passing the last access unit of a stream to the sample queue (<a href="https://github.com/google/ExoPlayer/issues/7909">#7909</a>). Incorporating fixes to resolve the issues that emerged in I-frame only HLS streams(<a href="https://github.com/androidx/media/issues/1150">#1150</a>) and H.262 HLS streams (<a href="https://github.com/androidx/media/issues/1126">#1126</a>).</li> <li>MP3: Prefer the data size from an <code translate="no" dir="ltr">Info</code> frame over the size reported by the underlying stream (e.g. file size, or HTTP <code translate="no" dir="ltr">Content-Length</code> header). This helps to exclude non-playable trailer data (e.g. album artwork) from constant bitrate seeking calculations, making seeks more accurate (<a href="https://github.com/androidx/media/issues/1376">#1376</a>).</li> <li>MP3: Use the frame count and other data in an <code translate="no" dir="ltr">Info</code> frame (if present) to compute an average bitrate for constant bitrate seeking, rather than extrapolating from the bitrate of the frame after the <code translate="no" dir="ltr">Info</code> frame, which may be artificially small, e.g. <code translate="no" dir="ltr">PCUT</code> frame (<a href="https://github.com/androidx/media/issues/1376">#1376</a>).</li> <li>Fix PCM audio format extraction in AVI containers.</li> </ul></li> <li>Audio: <ul> <li>Fix DTS:X Profile 2 encoding attributes for passthrough playback (<a href="https://github.com/androidx/media/pull/1299">#1299</a>).</li> <li>For offloaded playback, reset the tracking field for stream completion in <code translate="no" dir="ltr">DefaultAudioSink</code> prior to calling <code translate="no" dir="ltr">AudioTrack.stop()</code> so that <code translate="no" dir="ltr">AudioTrack.StreamEventCallback#onPresentationEnded</code> correctly identifies when all pending data has been played.</li> <li>Fix bug in <code translate="no" dir="ltr">SilenceSkippingAudioProcessor</code> where transitions between different audio formats (for example stereo to mono) can cause the processor to throw an exception (<a href="https://github.com/androidx/media/issues/1352">#1352</a>).</li> <li>Implement <code translate="no" dir="ltr">MediaCodecAudioRenderer.getDurationToProgressUs()</code> so that ExoPlayer will dynamically schedule its main work loop to when the MediaCodecAudioRenderer can make progress.</li> </ul></li> <li>Video: <ul> <li>Fix issue where <code translate="no" dir="ltr">Listener.onRenderedFirstFrame()</code> arrives too early when switching surfaces mid-playback.</li> <li>Fix decoder fallback logic for Dolby Vision to use a compatible AV1 decoder if needed (<a href="https://github.com/androidx/media/pull/1389">#1389</a>).</li> <li>Fix codec exception that may be caused by enabling a video renderer mid-playback.</li> </ul></li> <li>Text: <ul> <li>Fix issue where subtitles starting before a seek position are skipped. This issue was only introduced in Media3 1.4.0-alpha01.</li> <li>Change default subtitle parsing behavior so it happens during extraction instead of during rendering (see <a href="https://developer.android.com/media/media3/exoplayer/glossary#exoplayer">ExoPlayer&#39;s architecture diagram</a> for the difference between extraction and rendering). <ul> <li>This change can be overridden by calling <strong>both</strong> <code translate="no" dir="ltr">MediaSource.Factory.experimentalParseSubtitlesDuringExtraction(false)</code> and <code translate="no" dir="ltr">TextRenderer.experimentalSetLegacyDecodingEnabled(true)</code>. See the <a href="https://developer.android.com/media/media3/exoplayer/customization">docs on customization</a> for how to plumb these components into an <code translate="no" dir="ltr">ExoPlayer</code> instance. These methods (and all support for legacy subtitle decoding) will be removed in a future release.</li> <li>Apps with custom <code translate="no" dir="ltr">SubtitleDecoder</code> implementations need to update them to implement <code translate="no" dir="ltr">SubtitleParser</code> instead (and <code translate="no" dir="ltr">SubtitleParser.Factory</code> instead of <code translate="no" dir="ltr">SubtitleDecoderFactory</code>).</li> </ul></li> <li>PGS: Fix run-length decoding to resolve <code translate="no" dir="ltr">0</code> as a color index, instead of a literal color value (<a href="https://github.com/androidx/media/pull/1367">#1367</a>).</li> <li>CEA-708: Ignore <code translate="no" dir="ltr">rowLock</code> value. The CEA-708-E S-2023 spec states that <code translate="no" dir="ltr">rowLock</code> and <code translate="no" dir="ltr">columnLock</code> should both be assumed to be true, regardless of the values present in the stream (<code translate="no" dir="ltr">columnLock</code> support is not implemented, so it&#39;s effectively assumed to always be false). <ul> <li>This was originally included in the <code translate="no" dir="ltr">1.3.0-alpha01</code> release notes, but the change was accidentally reverted before the <code translate="no" dir="ltr">1.3.0-rc01</code> release. This is now fixed, so the change is present again.</li> </ul></li> <li>CEA-708: Avoid duplicate newlines being added by ExoPlayer&#39;s naive handling of the &#39;set pen location&#39; command (<a href="https://github.com/androidx/media/pull/1315">#1315</a>).</li> <li>Fix an <code translate="no" dir="ltr">IllegalArgumentException</code> from <code translate="no" dir="ltr">LegacySubtitleUtil</code> when a WebVTT subtitle sample contains no cues, e.g. as part of a DASH stream (<a href="https://github.com/androidx/media/issues/1516">#1516</a>).</li> </ul></li> <li>Metadata: <ul> <li>Fix mapping of MP4 to ID3 sort tags. Previously the &#39;album sort&#39; (<code translate="no" dir="ltr">soal</code>), &#39;artist sort&#39; (<code translate="no" dir="ltr">soar</code>) and &#39;album artist sort&#39; (<code translate="no" dir="ltr">soaa</code>) MP4 tags were wrongly mapped to the <code translate="no" dir="ltr">TSO2</code>, <code translate="no" dir="ltr">TSOA</code> and <code translate="no" dir="ltr">TSOP</code> ID3 tags (<a href="https://github.com/androidx/media/issues/1302">#1302</a>).</li> <li>Fix reading of MP4 (/iTunes) numeric <code translate="no" dir="ltr">gnre</code> (genre) and <code translate="no" dir="ltr">tmpo</code> (tempo) tags when the value is more than one byte long.</li> <li>Propagate ID3 <code translate="no" dir="ltr">TCON</code> frame to <code translate="no" dir="ltr">MediaMetadata.genre</code> (<a href="https://github.com/androidx/media/issues/1305">#1305</a>).</li> </ul></li> <li>Image: <ul> <li>Add support for non-square DASH thumbnail grids (<a href="https://github.com/androidx/media/pull/1300">#1300</a>).</li> <li>Add support for AVIF for API 34+.</li> <li>Allow <code translate="no" dir="ltr">null</code> as parameter for <code translate="no" dir="ltr">ExoPlayer.setImageOutput()</code> to clear a previously set <code translate="no" dir="ltr">ImageOutput</code>.</li> </ul></li> <li>DataSource: <ul> <li>Implement support for <code translate="no" dir="ltr">android.resource://package/id</code> raw resource URIs where <code translate="no" dir="ltr">package</code> is different to the package of the current application. This wasn&#39;t previously documented to work, but is a more efficient way of accessing resources in another package than by name.</li> <li>Eagerly check <code translate="no" dir="ltr">url</code> is non-null in the <code translate="no" dir="ltr">DataSpec</code> constructors. This parameter was already annotated to be non-null.</li> <li>Allow <code translate="no" dir="ltr">ByteArrayDataSource</code> to resolve a URI to a byte array during <code translate="no" dir="ltr">open()</code>, instead of being hard-coded at construction (<a href="https://github.com/androidx/media/issues/1405">#1405</a>).</li> </ul></li> <li>DRM: <ul> <li>Allow setting a <code translate="no" dir="ltr">LoadErrorHandlingPolicy</code> on <code translate="no" dir="ltr">DefaultDrmSessionManagerProvider</code> (<a href="https://github.com/androidx/media/issues/1271">#1271</a>).</li> </ul></li> <li>Effect: <ul> <li>Support multiple speed changes within the same <code translate="no" dir="ltr">EditedMediaItem</code> or <code translate="no" dir="ltr">Composition</code> in <code translate="no" dir="ltr">SpeedChangeEffect</code>.</li> <li>Support for HLG and PQ output from ultra HDR bitmap input.</li> <li>Add support for EGL_GL_COLORSPACE_BT2020_HLG_EXT, which improves HLG surface output in ExoPlayer.setVideoEffect and Transformer&#39;s Debug SurfaceView.</li> <li>Update Overlay matrix implementation to make it consistent with the documentation by flipping the x and y values applied in <code translate="no" dir="ltr">setOverlayFrameAnchor()</code>. If using <code translate="no" dir="ltr">OverlaySettings.Builder.setOverlayFrameAnchor()</code>, flip their x and y values by multiplying them by <code translate="no" dir="ltr">-1</code>.</li> <li>Fix bug where <code translate="no" dir="ltr">TimestampWrapper</code> crashes when used with <code translate="no" dir="ltr">ExoPlayer#setVideoEffects</code> (<a href="https://github.com/androidx/media/issues/821">#821</a>).</li> <li>Change default SDR color working space from linear colors to electrical BT 709 SDR video. Also provide third option to retain the original colorspace.</li> <li>Allow defining indeterminate z-order of EditedMediaItemSequences (<a href="https://github.com/androidx/media/pull/1055">#1055</a>).</li> <li>Maintain a consistent luminance range across different pieces of HDR content (uses the HLG range).</li> <li>Add support for Ultra HDR (bitmap) overlays on HDR content.</li> <li>Allow <code translate="no" dir="ltr">SeparableConvolution</code> effects to be used before API 26.</li> <li>Remove unused <code translate="no" dir="ltr">OverlaySettings.useHdr</code> since dynamic range of overlay and frame must match.</li> <li>Add HDR support for <code translate="no" dir="ltr">TextOverlay</code>. Luminance of the text overlay can be adjusted with <code translate="no" dir="ltr">OverlaySettings.Builder.setHdrLuminanceMultiplier()</code>.</li> </ul></li> <li>IMA extension: <ul> <li>Promote API that is required for apps to play <a href="https://developers.google.com/ad-manager/dynamic-ad-insertion/full-service">DAI ad streams</a> to stable.</li> <li>Add <code translate="no" dir="ltr">replaceAdTagParameters(Map &lt;String, String&gt;)</code> to <code translate="no" dir="ltr">ImaServerSideAdInsertionMediaSource.AdLoader</code> that allows replacing ad tag parameters at runtime.</li> <li>Fix bug where <code translate="no" dir="ltr">VideoAdPlayer.VideoAdPlayerCallback.onError()</code> was not called when a player error happened during ad playback (<a href="https://github.com/androidx/media/issues/1334">#1334</a>).</li> <li>Bump IMA SDK version to 3.33.0 to fix a <code translate="no" dir="ltr">NullPointerException</code> when using <code translate="no" dir="ltr">data://</code> ad tag URIs (<a href="https://github.com/androidx/media/issues/700">#700</a>).</li> </ul></li> <li>Session: <ul> <li>Change default of <code translate="no" dir="ltr">CommandButton.enabled</code> to <code translate="no" dir="ltr">true</code> and ensure the value can stay false for controllers even if the associated command is available.</li> <li>Add icon constants for <code translate="no" dir="ltr">CommandButton</code> that should be used instead of custom icon resources.</li> <li>Add <code translate="no" dir="ltr">MediaSessionService.isPlaybackOngoing()</code> to let apps query whether the service needs to be stopped in <code translate="no" dir="ltr">onTaskRemoved()</code> (<a href="https://github.com/androidx/media/issues/1219">#1219</a>).</li> <li>Add <code translate="no" dir="ltr">MediaSessionService.pauseAllPlayersAndStopSelf()</code> that conveniently allows to pause playback of all sessions and call <code translate="no" dir="ltr">stopSelf()</code> to terminate the lifecycle of the <code translate="no" dir="ltr">MediaSessionService</code>.</li> <li>Override <code translate="no" dir="ltr">MediaSessionService.onTaskRemoved(Intent)</code> to provide a safe default implementation that keeps the service running in the foreground if playback is ongoing or stops the service otherwise.</li> <li>Hide seekbar in the media notification for live streams by not setting the duration into the platform session metadata (<a href="https://github.com/androidx/media/issues/1256">#1256</a>).</li> <li>Align conversion of <code translate="no" dir="ltr">MediaMetadata</code> to <code translate="no" dir="ltr">MediaDescriptionCompat</code>, to use the same preferred order and logic when selecting metadata properties as in media1.</li> <li>Add <code translate="no" dir="ltr">MediaSession.sendError()</code> that allows sending non-fatal errors to Media3 controller. When using the notification controller (see <code translate="no" dir="ltr">MediaSession.getMediaNotificationControllerInfo()</code>), the custom error is used to update the <code translate="no" dir="ltr">PlaybackState</code> of the platform session to an error state with the given error information (<a href="https://github.com/androidx/media/issues/543">#543</a>).</li> <li>Add <code translate="no" dir="ltr">MediaSession.Callback.onPlayerInteractionFinished()</code> to inform sessions when a series of player interactions from a specific controller finished.</li> <li>Add <code translate="no" dir="ltr">SessionError</code> and use it in <code translate="no" dir="ltr">SessionResult</code> and <code translate="no" dir="ltr">LibraryResult</code> instead of the error code to provide more information about the error and how to resolve the error if possible.</li> <li>Publish the code for the media3 controller test app that can be used to test interactions with apps publishing a media session.</li> <li>Propagate extras passed to media3&#39;s <code translate="no" dir="ltr">MediaSession[Builder].setSessionExtras()</code> to a media1 controller&#39;s <code translate="no" dir="ltr">PlaybackStateCompat.getExtras()</code>.</li> <li>Map fatal and non-fatal errors to and from the platform session. A <code translate="no" dir="ltr">PlaybackException</code> is mapped to a fatal error state of the <code translate="no" dir="ltr">PlaybackStateCompat</code>. A <code translate="no" dir="ltr">SessionError</code> sent to the media notification controller with <code translate="no" dir="ltr">MediaSession.sendError(ControllerInfo, SessionError)</code> is mapped to a non-fatal error in <code translate="no" dir="ltr">PlaybackStateCompat</code> which means that error code and message are set but the state of the platform session remains different to <code translate="no" dir="ltr">STATE_ERROR</code>.</li> <li>Allow the session activity to be set per controller to override the global session activity. The session activity can be defined for a controller at connection time by creating a <code translate="no" dir="ltr">ConnectionResult</code> with <code translate="no" dir="ltr">AcceptedResultBuilder.setSessionActivivty(PendingIntent)</code>. Once connected, the session activity can be updated with <code translate="no" dir="ltr">MediaSession.setSessionActivity(ControllerInfo, PendingIntent)</code>.</li> <li>Improve error replication of calls to <code translate="no" dir="ltr">MediaLibrarySession.Callback</code>. Error replication can now be configured by using <code translate="no" dir="ltr">MediaLibrarySession.Builder.setLibraryErrorReplicationMode()</code> for choosing the error type or opt-ing out of error replication which is on by default.</li> </ul></li> <li>UI: <ul> <li>Add image display support to <code translate="no" dir="ltr">PlayerView</code> when connected to an <code translate="no" dir="ltr">ExoPlayer</code> (<a href="https://github.com/androidx/media/issues/1144">#1144</a>).</li> <li>Add customization of various icons in <code translate="no" dir="ltr">PlayerControlView</code> through xml attributes to allow different drawables per <code translate="no" dir="ltr">PlayerView</code> instance, rather than global overrides (<a href="https://github.com/androidx/media/issues/1200">#1200</a>).</li> <li>Work around a platform bug causing stretched/cropped video when using <code translate="no" dir="ltr">SurfaceView</code> inside a Compose <code translate="no" dir="ltr">AndroidView</code> on API 34 (<a href="https://github.com/androidx/media/issues/1237">#1237</a>).</li> </ul></li> <li>Downloads: <ul> <li>Ensure that <code translate="no" dir="ltr">DownloadHelper</code> does not leak unreleased <code translate="no" dir="ltr">Renderer</code> instances, which can eventually result in an app crashing with <code translate="no" dir="ltr">IllegalStateException: Too many receivers, total of 1000, registered for pid</code> (<a href="https://github.com/androidx/media/issues/1224">#1224</a>).</li> </ul></li> <li>Cronet Extension: <ul> <li>Fix <code translate="no" dir="ltr">SocketTimeoutException</code> in <code translate="no" dir="ltr">CronetDataSource</code>. In some versions of Cronet, the request provided by the callback is not always the same. This leads to callback not completing and request timing out (https://issuetracker.google.com/328442628).</li> </ul></li> <li>HLS Extension: <ul> <li>Fix bug where pending EMSG samples waiting for a discontinuity were delegated in <code translate="no" dir="ltr">HlsSampleStreamWrapper</code> with an incorrect offset causing an <code translate="no" dir="ltr">IndexOutOfBoundsException</code> or an <code translate="no" dir="ltr">IllegalArgumentException</code> (<a href="https://github.com/androidx/media/issues/1002">#1002</a>).</li> <li>Fix bug where non-primary playlists keep reloading for LL-HLS streams (<a href="https://github.com/androidx/media/issues/1240">#1240</a>).</li> <li>Fix bug where enabling CMCD for HLS with initialization segments resulted in <code translate="no" dir="ltr">Source Error</code> and <code translate="no" dir="ltr">IllegalArgumentException</code>.</li> <li>Fix bug where non-primary playing playlists are not refreshed during live playback (<a href="https://github.com/androidx/media/issues/1240">#1240</a>).</li> <li>Fix bug where enabling CMCD for HLS live streams causes <code translate="no" dir="ltr">ArrayIndexOutOfBoundsException</code> (<a href="https://github.com/androidx/media/issues/1395">#1395</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Fix bug where re-preparing a multi-period live stream can throw an <code translate="no" dir="ltr">IndexOutOfBoundsException</code> (<a href="https://github.com/androidx/media/issues/1329">#1329</a>).</li> <li>Add support for <code translate="no" dir="ltr">dashif:Laurl</code> license urls (<a href="https://github.com/androidx/media/issues/1345">#1345</a>).</li> </ul></li> <li>Cast Extension: <ul> <li>Fix bug that converted the album title of the <code translate="no" dir="ltr">MediaQueueItem</code> to the artist in the Media3 media item (<a href="https://github.com/androidx/media/pull/1255">#1255</a>).</li> </ul></li> <li>Test Utilities: <ul> <li>Implement <code translate="no" dir="ltr">onInit()</code> and <code translate="no" dir="ltr">onRelease()</code> in <code translate="no" dir="ltr">FakeRenderer</code>.</li> <li>Change <code translate="no" dir="ltr">TestPlayerRunHelper.runUntil()/playUntil()</code> methods to fail on nonfatal errors (e.g. those reported to <code translate="no" dir="ltr">AnalyticsListener.onVideoCodecError()</code>). Use the new <code translate="no" dir="ltr">TestPlayerRunHelper.run(player).ignoringNonFatalErrors().untilXXX()</code> method chain to disable this behavior.</li> </ul></li> <li>Demo app: <ul> <li>Use <code translate="no" dir="ltr">DefaultPreloadManager</code> in the short form demo app.</li> <li>Allow setting repeat mode with <code translate="no" dir="ltr">Intent</code> arguments from command line (<a href="https://github.com/androidx/media/pull/1266">#1266</a>).</li> <li>Use <code translate="no" dir="ltr">HttpEngineDataSource</code> as the <code translate="no" dir="ltr">HttpDataSource</code> when supported by the device.</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">CronetDataSourceFactory</code>. Use <code translate="no" dir="ltr">CronetDataSource.Factory</code> instead.</li> <li>Remove some <code translate="no" dir="ltr">DataSpec</code> constructors. Use <code translate="no" dir="ltr">DataSpec.Builder</code> instead.</li> <li>Remove <code translate="no" dir="ltr">setContentTypePredicate(Predicate)</code> method from <code translate="no" dir="ltr">DefaultHttpDataSource</code>, <code translate="no" dir="ltr">OkHttpDataSource</code> and <code translate="no" dir="ltr">CronetDataSource</code>. Use the equivalent method on each <code translate="no" dir="ltr">XXXDataSource.Factory</code> instead.</li> <li>Remove <code translate="no" dir="ltr">OkHttpDataSource</code> constructors and <code translate="no" dir="ltr">OkHttpDataSourceFactory</code>. Use <code translate="no" dir="ltr">OkHttpDataSource.Factory</code> instead.</li> <li>Remove <code translate="no" dir="ltr">PlayerMessage.setHandler(Handler)</code>. Use <code translate="no" dir="ltr">setLooper(Looper)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">Timeline.Window.isLive</code> field. Use the <code translate="no" dir="ltr">isLive()</code> method instead.</li> <li>Remove <code translate="no" dir="ltr">DefaultHttpDataSource</code> constructors. Use <code translate="no" dir="ltr">DefaultHttpDataSource.Factory</code> instead.</li> <li>Remove <code translate="no" dir="ltr">DashMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS</code>. Use <code translate="no" dir="ltr">DashMediaSource.DEFAULT_FALLBACK_TARGET_LIVE_OFFSET_MS</code> instead.</li> <li>Remove <code translate="no" dir="ltr">MediaCodecInfo.isSeamlessAdaptationSupported(Format, Format, boolean)</code>. Use <code translate="no" dir="ltr">MediaCodecInfo.canReuseCodec(Format, Format)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">DrmSessionManager.DUMMY</code> and <code translate="no" dir="ltr">getDummyDrmSessionManager()</code> method. Use <code translate="no" dir="ltr">DrmSessionManager.DRM_UNSUPPORTED</code> instead.</li> <li>Remove <code translate="no" dir="ltr">AnalyticsListener.onAudioInputFormatChanged(EventTime, Format)</code>, <code translate="no" dir="ltr">AnalyticsListener.onVideoInputFormatChanged(EventTime, Format)</code>, <code translate="no" dir="ltr">AudioRendererEventListener.onAudioInputFormatChanged(Format)</code>, <code translate="no" dir="ltr">VideoRendererEventListener.onVideoInputFormatChanged(Format)</code>. Use the overloads that take a <code translate="no" dir="ltr">DecoderReuseEvaluation</code> instead.</li> <li>Remove <code translate="no" dir="ltr">RendererSupport.FormatSupport</code> IntDef and <code translate="no" dir="ltr">FORMAT_HANDLED</code>, <code translate="no" dir="ltr">FORMAT_EXCEEDS_CAPABILITIES</code>, <code translate="no" dir="ltr">FORMAT_UNSUPPORTED_DRM</code>, <code translate="no" dir="ltr">FORMAT_UNSUPPORTED_SUBTYPE</code>, <code translate="no" dir="ltr">FORMAT_UNSUPPORTED_TYPE</code> constants. Use the equivalent IntDef and constants in <code translate="no" dir="ltr">androidx.media3.common.C</code> instead (e.g. <code translate="no" dir="ltr">C.FORMAT_HANDLED</code>).</li> <li>Remove <code translate="no" dir="ltr">Bundleable</code> interface. This includes removing all <code translate="no" dir="ltr">Bundleable.Creator&lt;Foo&gt; CREATOR</code> constant fields. Callers should use the <code translate="no" dir="ltr">Bundle toBundle()</code> and <code translate="no" dir="ltr">static Foo fromBundle(Bundle)</code> methods on each type instead.</li> </ul></li> </ul> <h3 id="1.4.0-rc01" data-text="Version 1.4.0-rc01" tabindex="-1">Version 1.4.0-rc01</h3> <p>July 10, 2024</p> <p>Use the 1.4.0 <a href="#1.4.0">stable version</a>.</p> <h3 id="1.4.0-beta01" data-text="Version 1.4.0-beta01" tabindex="-1">Version 1.4.0-beta01</h3> <p>June 26, 2024</p> <p>Use the 1.4.0 <a href="#1.4.0">stable version</a>.</p> <h3 id="1.4.0-alpha02" data-text="Version 1.4.0-alpha02" tabindex="-1">Version 1.4.0-alpha02</h3> <p>June 07, 2024</p> <p>Use the 1.4.0 <a href="#1.4.0">stable version</a>.</p> <h3 id="1.4.0-alpha01" data-text="Version 1.4.0-alpha01" tabindex="-1">Version 1.4.0-alpha01</h3> <p>April 17, 2024</p> <p>Use the 1.4.0 <a href="#1.4.0">stable version</a>.</p> <h2 id="version_130_3" data-text="Version 1.3.0" tabindex="-1">Version 1.3.0</h2> <h3 id="1.3.1" data-text="Version 1.3.1" tabindex="-1">Version 1.3.1</h3> <p>April 11, 2024</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.3.1</code> is released. Version 1.3.1 contains <a href="https://github.com/androidx/media/commits/1.3.1">these commits</a>.</p> <ul> <li>Common Library: <ul> <li>Add <code translate="no" dir="ltr">Format.labels</code> to allow localized or other alternative labels.</li> </ul></li> <li>ExoPlayer: <ul> <li>Fix issue where <code translate="no" dir="ltr">PreloadMediaPeriod</code> cannot retain the streams when it is preloaded again.</li> <li>Apply the correct corresponding <code translate="no" dir="ltr">TrackSelectionResult</code> to the playing period in track reselection.</li> <li>Start early-enabled renderers only after advancing the playing period when transitioning between media items (<a href="https://github.com/androidx/media/issues/1017">#1017</a>).</li> <li>Add missing return type to proguard <code translate="no" dir="ltr">-keepclasseswithmembers</code> rule for <code translate="no" dir="ltr">DefaultVideoFrameProcessor.Factory.Builder.build()</code> (<a href="https://github.com/androidx/media/issues/1187">#1187</a>).</li> </ul></li> <li>Transformer: <ul> <li>Add workaround for exception thrown due to <code translate="no" dir="ltr">MediaMuxer</code> not supporting negative presentation timestamps before API 30.</li> </ul></li> <li>Track Selection: <ul> <li><code translate="no" dir="ltr">DefaultTrackSelector</code>: Prefer video tracks with a &#39;reasonable&#39; frame rate (&gt;=10fps) over those with a lower or unset frame rate. This ensures the player selects the &#39;real&#39; video track in MP4s extracted from motion photos that can contain two HEVC tracks where one has a higher resolution but a very small number of frames (<a href="https://github.com/androidx/media/issues/1051">#1051</a>).</li> </ul></li> <li>Extractors: <ul> <li>Fix issue where padding was not skipped when reading odd-sized chunks from WAV files (<a href="https://github.com/androidx/media/pull/1117">#1117</a>).</li> <li>MP3: Populate <code translate="no" dir="ltr">Format.averageBitrate</code> from metadata frames such as <code translate="no" dir="ltr">XING</code> and <code translate="no" dir="ltr">VBRI</code>.</li> <li>MPEG-TS: Revert a change that aimed to ensure the last frame is rendered by passing the last access unit of a stream to the sample queue (<a href="https://github.com/google/ExoPlayer/issues/7909">#7909</a>). This is due to the change causing new problems with I-frame only HLS streams (<a href="https://github.com/google/ExoPlayer/issues/1150">#1150</a>) and H.262 HLS streams (<a href="https://github.com/google/ExoPlayer/issues/1126">#1126</a>).</li> </ul></li> <li>Audio: <ul> <li>Allow renderer recovery by disabling offload if audio track fails to initialize in offload mode.</li> </ul></li> <li>Video: <ul> <li>Add workaround for a device issue on Galaxy Tab S7 FE, Chromecast with Google TV, and Lenovo M10 FHD Plus that causes 60fps H265 streams to be marked as unsupported</li> <li>Add workaround that ensures the first frame is always rendered while tunneling even if the device does not do this automatically as required by the API (<a href="https://github.com/androidx/media/issues/1169">#1169</a>). (<a href="https://github.com/androidx/media/issues/966">#966</a>).</li> <li>Fix issue where HDR color info handling causes codec misbehavior and prevents adaptive format switches for SDR video tracks (<a href="https://github.com/androidx/media/issues/1158">#1158</a>).</li> </ul></li> <li>Text: <ul> <li>WebVTT: Prevent directly consecutive cues from creating spurious additional <code translate="no" dir="ltr">CuesWithTiming</code> instances from <code translate="no" dir="ltr">WebvttParser.parse</code> (<a href="https://github.com/androidx/media/issues/1177">#1177</a>).</li> </ul></li> <li>DRM: <ul> <li>Work around a <code translate="no" dir="ltr">NoSuchMethodError</code> which can be thrown by the <code translate="no" dir="ltr">MediaDrm</code> framework instead of <code translate="no" dir="ltr">ResourceBusyException</code> or <code translate="no" dir="ltr">NotProvisionedException</code> on some Android 14 devices (<a href="https://github.com/androidx/media/issues/1145">#1145</a>).</li> </ul></li> <li>Effect: <ul> <li>Improved PQ to SDR tone-mapping by converting color spaces.</li> </ul></li> <li>Session: <ul> <li>Fix issue where the current position jumps back when the controller replaces the current item (<a href="https://github.com/androidx/media/issues/951">#951</a>).</li> <li>Fix issue where <code translate="no" dir="ltr">MediaMetadata</code> with just non-null <code translate="no" dir="ltr">extras</code> is not transmitted between media controllers and sessions (<a href="https://github.com/androidx/media/issues/1176">#1176</a>).</li> </ul></li> <li>UI: <ul> <li>Fallback to include audio track language name if <code translate="no" dir="ltr">Locale</code> cannot identify a display name (<a href="https://github.com/androidx/media/issues/988">#988</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Populate all <code translate="no" dir="ltr">Label</code> elements from the manifest into <code translate="no" dir="ltr">Format.labels</code> (<a href="https://github.com/androidx/media/pull/1054">#1054</a>).</li> </ul></li> <li>RTSP Extension: <ul> <li>Skip empty session information values (i-tags) in SDP parsing (<a href="https://github.com/androidx/media/issues/1087">#1087</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.): <ul> <li>Disable the MIDI extension as a local dependency by default because it requires an additional Maven repository to be configured. Users who need this module from a local dependency <a href="https://github.com/androidx/media/blob/main/README.md#midi-module">can re-enable it</a>.</li> </ul></li> </ul> <h3 id="1.3.0" data-text="Version 1.3.0" tabindex="-1">Version 1.3.0</h3> <p>March 6, 2024</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.3.0</code> is released. Version 1.3.0 contains <a href="https://github.com/androidx/media/commits/1.3.0">these commits</a>.</p> <ul> <li>Common Library: <ul> <li>Implement support for <code translate="no" dir="ltr">android.resource://package/[type/]name</code> raw resource URIs where <code translate="no" dir="ltr">package</code> is different to the package of the current application. This has always been documented to work, but wasn&#39;t correctly implemented until now.</li> <li>Normalize MIME types set by app code or read from media to be fully lower-case.</li> <li>Define ads with a full <code translate="no" dir="ltr">MediaItem</code> instead of a single <code translate="no" dir="ltr">Uri</code> in <code translate="no" dir="ltr">AdPlaybackState</code>.</li> <li>Increase <code translate="no" dir="ltr">minSdk</code> to 19 (Android KitKat). This is <a href="https://android-developers.googleblog.com/2023/10/androidx-minsdkversion-19.html">aligned with all other AndroidX libraries</a>, and is required for us to upgrade to the latest versions of our AndroidX dependencies.</li> <li>Populate both <code translate="no" dir="ltr">artworkUri</code> and <code translate="no" dir="ltr">artworkData</code> in <code translate="no" dir="ltr">MediaMetadata.Builder.populate(MediaMetadata)</code> when at least one of them is non-null (<a href="https://github.com/androidx/media/issues/964">#964</a>).</li> </ul></li> <li>ExoPlayer: <ul> <li>Add <code translate="no" dir="ltr">PreloadMediaSource</code> and <code translate="no" dir="ltr">PreloadMediaPeriod</code> that allows apps to preload a content media source at a specific start position before playback. <code translate="no" dir="ltr">PreloadMediaSource</code> takes care of preparing the content media source to receive the <code translate="no" dir="ltr">Timeline</code>, preparing and caching the period at the given start position, selecting tracks and loading media data for the period. Apps control the preload progress by implementing <code translate="no" dir="ltr">PreloadMediaSource.PreloadControl</code> and set the preloaded source to the player for playback.</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.setImageOutput</code> that allows apps to set <code translate="no" dir="ltr">ImageRenderer.ImageOutput</code>.</li> <li><code translate="no" dir="ltr">DefaultRenderersFactory</code> now provides an <code translate="no" dir="ltr">ImageRenderer</code> to the player by default with null <code translate="no" dir="ltr">ImageOutput</code> and <code translate="no" dir="ltr">ImageDecoder.Factory.DEFAULT</code>.</li> <li>Emit <code translate="no" dir="ltr">Player.Listener.onPositionDiscontinuity</code> event when silence is skipped (<a href="https://github.com/androidx/media/issues/765">#765</a>).</li> <li>Add experimental support for parsing subtitles during extraction. You can enable this using <code translate="no" dir="ltr">MediaSource.Factory.experimentalParseSubtitlesDuringExtraction()</code>.</li> <li>Support adaptive media sources with <code translate="no" dir="ltr">PreloadMediaSource</code>.</li> <li>Implement <code translate="no" dir="ltr">HttpEngineDataSource</code>, an <code translate="no" dir="ltr">HttpDataSource</code> using the <a href="https://developer.android.com/reference/android/net/http/HttpEngine">HttpEngine</a> API.</li> <li>Prevent subclassing <code translate="no" dir="ltr">CompositeSequenceableLoader</code>. This component was <a href="https://github.com/androidx/media/commit/0de57cbfae7165dd3bb829e323d089cd312b4b1b">previously made extensible</a> but was never subclassed within the library. Customizations can be done by wrapping an instance using the <a href="https://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a> and implementing a custom <code translate="no" dir="ltr">CompositeSequenceableLoaderFactory</code>.</li> <li>Fix issue where repeating the same time causes metadata from this item to be cleared (<a href="https://github.com/androidx/media/issues/1007">#1007</a>).</li> <li>Rename <code translate="no" dir="ltr">experimentalSetSubtitleParserFactory</code> methods on <code translate="no" dir="ltr">BundledChunkExtractor.Factory</code> and <code translate="no" dir="ltr">DefaultHlsExtractorFactory</code> to <code translate="no" dir="ltr">setSubtitleParserFactory</code> and disallow passing <code translate="no" dir="ltr">null</code>. Use the new <code translate="no" dir="ltr">experimentalParseSubtitlesDuringExtraction(boolean)</code> methods to control parsing behaviour.</li> <li>Add support for customising the <code translate="no" dir="ltr">SubtitleParser.Factory</code> used during extraction. This can be achieved with <code translate="no" dir="ltr">MediaSource.Factory.setSubtitleParserFactory()</code>.</li> <li>Add source prefix to all <code translate="no" dir="ltr">Format.id</code> fields generated from <code translate="no" dir="ltr">MergingMediaSource</code>. This helps to identify which source produced a <code translate="no" dir="ltr">Format</code> (<a href="https://github.com/androidx/media/issues/883">#883</a>).</li> <li>Fix the regex used for validating custom Common Media Client Data (CMCD) key names by modifying it to only check for hyphen (<a href="https://github.com/androidx/media/issues/1028">#1028</a>).</li> <li>Stop double-encoding CMCD query parameters (<a href="https://github.com/androidx/media/issues/1075">#1075</a>).</li> </ul></li> <li>Transformer: <ul> <li>Add support for flattening H.265/HEVC SEF slow motion videos.</li> <li>Increase transmuxing speed, especially for &#39;remove video&#39; edits.</li> <li>Add API to ensure that the output file starts on a video frame. This can make the output of trimming operations more compatible with player implementations that don&#39;t show the first video frame until its presentation timestamp (<a href="https://github.com/androidx/media/issues/829">#829</a>).</li> <li>Add support for optimizing single asset MP4 trim operations.</li> <li>Add support to ensure a video frame has the first timestamp in the output file. Fixes output files beginning with black frame on iOS based players (<a href="https://github.com/androidx/media/issues/829">#829</a>).</li> </ul></li> <li>Track Selection: <ul> <li>Add <code translate="no" dir="ltr">DefaultTrackSelector.selectImageTrack</code> to enable image track selection.</li> <li>Add <code translate="no" dir="ltr">TrackSelectionParameters.isPrioritizeImageOverVideoEnabled</code> to determine whether to select an image track if both an image track and a video track are available. The default value is <code translate="no" dir="ltr">false</code> which means selecting a video track is prioritized.</li> </ul></li> <li>Extractors: <ul> <li>Add additional AV1C parsing to MP4 extractor to retrieve <code translate="no" dir="ltr">ColorInfo.colorSpace</code>, <code translate="no" dir="ltr">ColorInfo.colorTransfer</code>, and <code translate="no" dir="ltr">ColorInfo.colorRange</code> values (<a href="https://github.com/androidx/media/pull/692">#692</a>).</li> <li>MP3: Use constant bitrate (CBR) seeking for files with an <code translate="no" dir="ltr">Info</code> header (the CBR equivalent of the <code translate="no" dir="ltr">Xing</code> header). Previously we used the seek table from the <code translate="no" dir="ltr">Info</code> header, but this results in less precise seeking than if we ignore it and assume the file is CBR.</li> <li>MPEG2-TS: Add DTS, DTS-LBR and DTS:X Profile2 support (<a href="https://github.com/androidx/media/pull/275">#275</a>).</li> <li>Extract audio types from TS descriptors and map them to role flags, allowing users to make better-informed audio track selections (<a href="https://github.com/androidx/media/pull/973">#973</a>).</li> </ul></li> <li>Audio: <ul> <li>Improve silence skipping algorithm with smooth volume ramp; retained minimal silence and more natural silence durations (<a href="https://github.com/google/ExoPlayer/issues/7423">#7423</a>).</li> <li>Report the skipped silence more deterministically (<a href="https://github.com/androidx/media/issues/1035">#1035</a>).</li> </ul></li> <li>Video: <ul> <li>Change the <code translate="no" dir="ltr">MediaCodecVideoRenderer</code> constructor that takes a <code translate="no" dir="ltr">VideoFrameProcessor.Factory</code> argument and replace it with a constructor that takes a <code translate="no" dir="ltr">VideoSinkProvider</code> argument. Apps that want to inject a custom <code translate="no" dir="ltr">VideoFrameProcessor.Factory</code> can instantiate a <code translate="no" dir="ltr">CompositingVideoSinkProvider</code> that uses the custom <code translate="no" dir="ltr">VideoFrameProcessor.Factory</code> and pass the video sink provider to <code translate="no" dir="ltr">MediaCodecVideoRenderer</code>.</li> </ul></li> <li>Text: <ul> <li>Fix serialization of bitmap cues to resolve <code translate="no" dir="ltr">Tried to marshall a Parcel that contained Binder objects</code> error when using <code translate="no" dir="ltr">DefaultExtractorsFactory.setTextTrackTranscodingEnabled</code> (<a href="https://github.com/androidx/media/issues/836">#836</a>).</li> <li>CEA-708: Ignore <code translate="no" dir="ltr">rowLock</code> value. The CEA-708-E S-2023 spec states that <code translate="no" dir="ltr">rowLock</code> and <code translate="no" dir="ltr">columnLock</code> should both be assumed to be true, regardless of the values present in the stream (<code translate="no" dir="ltr">columnLock</code> support is not implemented, so it&#39;s effectively assumed to always be false).</li> </ul></li> <li>Image: <ul> <li>Add support for DASH thumbnails. Grid images are cropped and individual thumbnails are provided to <code translate="no" dir="ltr">ImageOutput</code> close to their presentation times.</li> </ul></li> <li>DRM: <ul> <li>Play &#39;clear lead&#39; unencrypted samples in DRM content immediately by default, even if the keys for the later encrypted samples aren&#39;t ready yet. This may lead to mid-playback stalls if the keys still aren&#39;t ready when the playback position reaches the encrypted samples (but previously playback wouldn&#39;t have started at all by this point). This behavior can be disabled with <a href="https://developer.android.com/reference/androidx/media3/common/MediaItem.DrmConfiguration.Builder#setPlayClearContentWithoutKey(boolean)"><code translate="no" dir="ltr">MediaItem.DrmConfiguration.Builder.setPlayClearContentWithoutKey</code></a> or <a href="https://developer.android.com/reference/androidx/media3/exoplayer/drm/DefaultDrmSessionManager.Builder#setPlayClearSamplesWithoutKeys(boolean)"><code translate="no" dir="ltr">DefaultDrmSessionManager.Builder.setPlayClearSamplesWithoutKeys</code></a>.</li> </ul></li> <li>IMA extension: <ul> <li>Fix issue where DASH and HLS ads without the appropriate file extension can&#39;t be played.</li> </ul></li> <li>Session: <ul> <li>Disable double-click detection for TV apps (<a href="https://github.com/androidx/media/issues/962">#962</a>).</li> <li>Fix issue where <code translate="no" dir="ltr">MediaItem.RequestMetadata</code> with just non-null extras is not transmitted between media controllers and sessions.</li> <li>Add constructor to <code translate="no" dir="ltr">MediaLibrarySession.Builder</code> that only takes a <code translate="no" dir="ltr">Context</code> instead of a <code translate="no" dir="ltr">MediaLibraryService</code>.</li> </ul></li> <li>HLS Extension: <ul> <li>Reduce <code translate="no" dir="ltr">HlsMediaPeriod</code> to package-private visibility. This type shouldn&#39;t be directly depended on from outside the HLS package.</li> <li>Resolve seeks to beginning of a segment more efficiently (<a href="https://github.com/androidx/media/pull/1031">#1031</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.): <ul> <li>MIDI decoder: Ignore SysEx event messages (<a href="https://github.com/androidx/media/pull/710">#710</a>).</li> </ul></li> <li>Test Utilities: <ul> <li>Don&#39;t pause playback in <code translate="no" dir="ltr">TestPlayerRunHelper.playUntilPosition</code>. The test keeps the playback in a playing state, but suspends progress until the test is able to add assertions and further actions.</li> </ul></li> <li>Demo app: <ul> <li>Add a shortform demo module to demo the usage of <code translate="no" dir="ltr">PreloadMediaSource</code> with the short-form content use case.</li> </ul></li> </ul> <h3 id="1.3.0-rc01" data-text="Version 1.3.0-rc01" tabindex="-1">Version 1.3.0-rc01</h3> <p>February 22, 2024</p> <p>Use the <a href="#1.3.0">1.3.0 stable version</a>.</p> <h3 id="1.3.0-beta01" data-text="Version 1.3.0-beta01" tabindex="-1">Version 1.3.0-beta01</h3> <p>February 7, 2024</p> <p>Use the <a href="#1.3.0">1.3.0 stable version</a>.</p> <h3 id="1.3.0-alpha01" data-text="Version 1.3.0-alpha01" tabindex="-1">Version 1.3.0-alpha01</h3> <p>January 15, 2024</p> <p>Use the <a href="#1.3.0">1.3.0 stable version</a>.</p> <h2 id="version_120_3" data-text="Version 1.2.0" tabindex="-1">Version 1.2.0</h2> <h3 id="version_121_2" data-text="Version 1.2.1" tabindex="-1">Version 1.2.1</h3> <p>January 9, 2024</p> <ul> <li>ExoPlayer: <ul> <li>Fix issue where manual seeks outside of the <code translate="no" dir="ltr">LiveConfiguration.min/maxOffset</code> range keep adjusting the offset back to <code translate="no" dir="ltr">min/maxOffset</code>.</li> <li>Fix issue that OPUS and VORBIS channel layouts are wrong for 3, 5, 6, 7 and 8 channels (<a href="https://github.com/google/ExoPlayer/issues/8396">#8396</a>).</li> <li>Fix issue where track selections after seek to zero in a live stream incorrectly let the stream start at its default position (<a href="https://github.com/google/ExoPlayer/issues/9347">#9347</a>).</li> <li>Fix the issue where new instances of <code translate="no" dir="ltr">CmcdData.Factory</code> were receiving negative values for <code translate="no" dir="ltr">bufferedDurationUs</code> from chunk sources, resulting in an <code translate="no" dir="ltr">IllegalArgumentException</code> (<a href="https://github.com/androidx/media/issues/888">#888</a>).</li> </ul></li> <li>Transformer: <ul> <li>Work around an issue where the encoder would throw at configuration time due to setting a high operating rate.</li> </ul></li> <li>Extractors: <ul> <li>Mark secondary (unplayable) HEVC tracks in JPEG motion photos as <code translate="no" dir="ltr">ROLE_FLAG_ALTERNATE</code> to prevent them being automatically selected for playback because of their higher resolution.</li> <li>Fix wrong keyframe detection for TS H264 streams (<a href="https://github.com/androidx/media/pull/864">#864</a>).</li> <li>Fix duration estimation of TS streams that are longer than 47721 seconds (<a href="https://github.com/androidx/media/issues/855">#855</a>).</li> </ul></li> <li>Audio: <ul> <li>Fix handling of EOS for <code translate="no" dir="ltr">SilenceSkippingAudioProcessor</code> when called multiple times (<a href="https://github.com/androidx/media/issues/712">#712</a>).</li> </ul></li> <li>Video: <ul> <li>Add workaround for a device issue on Galaxy Tab S7 FE, Chromecast with Google TV, and Lenovo M10 FHD Plus that causes 60fps AVC streams to be marked as unsupported (<a href="https://github.com/androidx/media/issues/693">#693</a>).</li> </ul></li> <li>Metadata: <ul> <li>Fix bug where <code translate="no" dir="ltr">MediaMetadata</code> was only populated from Vorbis comments with upper-case keys (<a href="https://github.com/androidx/media/issues/876">#876</a>).</li> <li>Catch <code translate="no" dir="ltr">OutOfMemoryError</code> when parsing very large ID3 frames, meaning playback can continue without the tag info instead of playback failing completely.</li> </ul></li> <li>DRM: <ul> <li>Extend workaround for spurious ClearKey <code translate="no" dir="ltr">https://default.url</code> license URL to API 33+ (previously the workaround only applied on API 33 exactly) (<a href="https://github.com/androidx/media/pull/837">#837</a>).</li> <li>Fix <code translate="no" dir="ltr">ERROR_DRM_SESSION_NOT_OPENED</code> when switching from encrypted to clear content without a surface attached to the player. The error was due to incorrectly using a secure decoder to play the clear content.</li> </ul></li> <li>Session: <ul> <li>Put the custom keys and values in <code translate="no" dir="ltr">MediaMetadataCompat</code> to <code translate="no" dir="ltr">MediaMetadata.extras</code> and <code translate="no" dir="ltr">MediaMetadata.extras</code> to <code translate="no" dir="ltr">MediaMetadataCompat</code> (<a href="https://github.com/androidx/media/issues/756">#756</a>, <a href="https://github.com/androidx/media/issues/802">#802</a>).</li> <li>Fix broadcasting <code translate="no" dir="ltr">notifyChildrenChanged</code> for legacy controllers (<a href="https://github.com/androidx/media/issues/644">#644</a>).</li> <li>Fix a bug where setting a negative time for a disabled <code translate="no" dir="ltr">setWhen</code> timer of the notification caused a crash on some devices (<a href="https://github.com/androidx/media/issues/903">#903</a>).</li> <li>Fix <code translate="no" dir="ltr">IllegalStateException</code> when the media notification controller hasn&#39;t completed connecting when the first notification update is requested (<a href="https://github.com/androidx/media/issues/917">#917</a>).</li> </ul></li> <li>UI: <ul> <li>Fix issue where forward and rewind buttons are not visible when used with Material Design in a BottomSheetDialogFragment (<a href="https://github.com/androidx/media/issues/511">#511</a>).</li> <li>Fix issue where the numbers in the fast forward button of the <code translate="no" dir="ltr">PlayerControlView</code> were misaligned (<a href="https://github.com/androidx/media/issues/547">#547</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Parse &quot;f800&quot; as channel count of 5 for Dolby in DASH manifest (<a href="https://github.com/androidx/media/issues/688">#688</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.): <ul> <li>MIDI: Fix issue where seeking forward skips the Program Change events (<a href="https://github.com/androidx/media/issues/704">#704</a>).</li> <li>Migrate to FFmpeg 6.0 and update supported NDK to <code translate="no" dir="ltr">r26b</code> (<a href="https://github.com/androidx/media/pull/707">#707</a>, <a href="https://github.com/androidx/media/pull/867">#867</a>).</li> </ul></li> <li>Cast Extension: <ul> <li>Sanitize creation of a <code translate="no" dir="ltr">Timeline</code> to not crash the app when loading media fails on the cast device (<a href="https://github.com/androidx/media/issues/708">#708</a>).</li> </ul></li> </ul> <h3 id="1.2.0" data-text="Version 1.2.0" tabindex="-1">Version 1.2.0</h3> <p>November 15, 2023</p> <ul> <li>Common Library: <ul> <li>Add a <code translate="no" dir="ltr">@Nullable Throwable</code> parameter to the methods in the <code translate="no" dir="ltr">Log.Logger</code> interface. The <code translate="no" dir="ltr">message</code> parameter to these methods no longer contains any information about the <code translate="no" dir="ltr">Throwable</code> passed to the <code translate="no" dir="ltr">Log.{d,i,w,e}()</code> methods, so implementations will need to manually append this information if desired (possibly using <code translate="no" dir="ltr">Logger.appendThrowableString(String, Throwable)</code>).</li> <li>Fix Kotlin compatibility issue where nullable generic type parameters and nullable array element types are not detected as nullable. Examples are <code translate="no" dir="ltr">TrackSelectorResult</code> and <code translate="no" dir="ltr">SimpleDecoder</code> method parameters (<a href="https://github.com/google/ExoPlayer/issues/6792">#6792</a>).</li> <li>Change default UI and notification behavior in <code translate="no" dir="ltr">Util.shouldShowPlayButton</code> to show a &quot;play&quot; button while playback is temporarily suppressed (e.g. due to transient audio focus loss). The legacy behavior can be maintained by using <code translate="no" dir="ltr">PlayerView.setShowPlayButtonIfPlaybackIsSuppressed(false)</code> or <code translate="no" dir="ltr">MediaSession.Builder.setShowPlayButtonIfPlaybackIsSuppressed(false)</code> (<a href="https://github.com/google/ExoPlayer/issues/11213">#11213</a>).</li> <li>Upgrade <code translate="no" dir="ltr">androidx.annotation:annotation-experimental</code> to <code translate="no" dir="ltr">1.3.1</code> to fix https://issuetracker.google.com/251172715.</li> <li>Move <code translate="no" dir="ltr">ExoPlayer.setAudioAttributes</code> to the <code translate="no" dir="ltr">Player</code> interface.</li> </ul></li> <li>ExoPlayer: <ul> <li>Fix seeking issues in AC4 streams caused by not identifying decode-only samples correctly (<a href="https://github.com/google/ExoPlayer/issues/11000">#11000</a>).</li> <li>Add suppression of playback on unsuitable audio output devices (e.g. the built-in speaker on Wear OS devices) when this feature is enabled via <code translate="no" dir="ltr">ExoPlayer.Builder.setSuppressPlaybackOnUnsuitableOutput</code>. The playback suppression reason will be updated as <code translate="no" dir="ltr">Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT</code> if playback is attempted when no suitable audio outputs are available, or if all suitable outputs are disconnected during playback. The suppression reason will be removed when a suitable output is connected.</li> <li>Add <code translate="no" dir="ltr">MediaSource.canUpdateMediaItem</code> and <code translate="no" dir="ltr">MediaSource.updateMediaItem</code> to accept <code translate="no" dir="ltr">MediaItem</code> updates after creation via <code translate="no" dir="ltr">Player.replaceMediaItem(s)</code>.</li> <li>Allow <code translate="no" dir="ltr">MediaItem</code> updates for all <code translate="no" dir="ltr">MediaSource</code> classes provided by the library via <code translate="no" dir="ltr">Player.replaceMediaItem(s)</code> (<a href="https://github.com/androidx/media/issues/33">#33</a>, <a href="https://github.com/google/ExoPlayer/issues/9978">#9978</a>).</li> <li>Rename <code translate="no" dir="ltr">MimeTypes.TEXT_EXOPLAYER_CUES</code> to <code translate="no" dir="ltr">MimeTypes.APPLICATION_MEDIA3_CUES</code>.</li> <li>Add <code translate="no" dir="ltr">PngExtractor</code> that sends and reads a whole PNG file into the <code translate="no" dir="ltr">TrackOutput</code> as one sample.</li> <li>Enhance <code translate="no" dir="ltr">SequenceableLoader.continueLoading(long)</code> method in the <code translate="no" dir="ltr">SequenceableLoader</code> interface to <code translate="no" dir="ltr">SequenceableLoader.continueLoading(LoadingInfo loadingInfo)</code>. <code translate="no" dir="ltr">LoadingInfo</code> contains additional parameters, including <code translate="no" dir="ltr">playbackSpeed</code> and <code translate="no" dir="ltr">lastRebufferRealtimeMs</code> in addition to the existing <code translate="no" dir="ltr">playbackPositionUs</code>.</li> <li>Enhance <code translate="no" dir="ltr">ChunkSource.getNextChunk(long, long, List, ChunkHolder)</code> method in the <code translate="no" dir="ltr">ChunkSource</code> interface to <code translate="no" dir="ltr">ChunkSource.getNextChunk(LoadingInfo, long, List, ChunkHolder)</code>.</li> <li>Add additional fields to Common Media Client Data (CMCD) logging: buffer starvation (<code translate="no" dir="ltr">bs</code>), deadline (<code translate="no" dir="ltr">dl</code>), playback rate (<code translate="no" dir="ltr">pr</code>) and startup (<code translate="no" dir="ltr">su</code>) (<a href="https://github.com/google/ExoPlayer/issues/8699">#8699</a>).</li> <li>Add luma and chroma bitdepth to <code translate="no" dir="ltr">ColorInfo</code> (<a href="https://github.com/androidx/media/pull/491">#491</a>).</li> <li>Add additional fields to Common Media Client Data (CMCD) logging: next object request (<code translate="no" dir="ltr">nor</code>) and next range request (<code translate="no" dir="ltr">nrr</code>) (<a href="https://github.com/google/ExoPlayer/issues/8699">#8699</a>).</li> <li>Add functionality to transmit Common Media Client Data (CMCD) data using query parameters (<a href="https://github.com/androidx/media/issues/553">#553</a>).</li> <li>Fix <code translate="no" dir="ltr">ConcurrentModificationException</code> in <code translate="no" dir="ltr">ExperimentalBandwidthMeter</code> (<a href="https://github.com/androidx/media/issues/612">#612</a>).</li> <li>Add <code translate="no" dir="ltr">MediaPeriodId</code> parameter to <code translate="no" dir="ltr">CompositeMediaSource.getMediaTimeForChildMediaTime</code>.</li> <li>Support <code translate="no" dir="ltr">ClippingMediaSource</code> (and other sources with period/window time offsets) in <code translate="no" dir="ltr">ConcatenatingMediaSource2</code> (<a href="https://github.com/google/ExoPlayer/issues/11226">#11226</a>).</li> <li>Change <code translate="no" dir="ltr">BaseRenderer.onStreamChanged()</code> to also receive a <code translate="no" dir="ltr">MediaPeriodId</code> argument.</li> </ul></li> <li>Transformer: <ul> <li>Parse EXIF rotation data for image inputs.</li> <li>Remove <code translate="no" dir="ltr">TransformationRequest.HdrMode</code> annotation type and its associated constants. Use <code translate="no" dir="ltr">Composition.HdrMode</code> and its associated constants instead.</li> <li>Simplify the <code translate="no" dir="ltr">OverlaySettings</code> to fix rotation issues.</li> <li>Changed <code translate="no" dir="ltr">frameRate</code> and <code translate="no" dir="ltr">durationUs</code> parameters of <code translate="no" dir="ltr">SampleConsumer.queueInputBitmap</code> to <code translate="no" dir="ltr">TimestampIterator</code>.</li> </ul></li> <li>Track Selection: <ul> <li>Add <code translate="no" dir="ltr">DefaultTrackSelector.Parameters.allowAudioNonSeamlessAdaptiveness</code> to explicitly allow or disallow non-seamless adaptation. The default stays at its current behavior of <code translate="no" dir="ltr">true</code>.</li> </ul></li> <li>Extractors: <ul> <li>MPEG-TS: Ensure the last frame is rendered by passing the last access unit of a stream to the sample queue (<a href="https://github.com/google/ExoPlayer/issues/7909">#7909</a>).</li> <li>Fix typo when determining <code translate="no" dir="ltr">rotationDegrees</code>. Changed <code translate="no" dir="ltr">projectionPosePitch</code> to <code translate="no" dir="ltr">projectionPoseRoll</code> (<a href="https://github.com/androidx/media/pull/461">#461</a>).</li> <li>Remove the assumption that <code translate="no" dir="ltr">Extractor</code> instances can be directly inspected with <code translate="no" dir="ltr">instanceof</code>. If you want runtime access to the implementation details of an <code translate="no" dir="ltr">Extractor</code> you must first call <code translate="no" dir="ltr">Extractor.getUnderlyingInstance</code>.</li> <li>Add <code translate="no" dir="ltr">BmpExtractor</code>.</li> <li>Add <code translate="no" dir="ltr">WebpExtractor</code>.</li> <li>Add <code translate="no" dir="ltr">HeifExtractor</code>.</li> <li>Add <a href="https://developer.apple.com/standards/qtff-2001.pdf">QuickTime classic</a> support to <code translate="no" dir="ltr">Mp4Extractor</code>.</li> </ul></li> <li>Audio: <ul> <li>Add support for 24/32-bit big-endian PCM in MP4 and Matroska, and parse PCM encoding for <code translate="no" dir="ltr">lpcm</code> in MP4.</li> <li>Add support for extracting Vorbis audio in MP4.</li> <li>Add <code translate="no" dir="ltr">AudioSink.getFormatOffloadSupport(Format)</code> that retrieves level of offload support the sink can provide for the format through a <code translate="no" dir="ltr">DefaultAudioOffloadSupportProvider</code>. It returns the new <code translate="no" dir="ltr">AudioOffloadSupport</code> that contains <code translate="no" dir="ltr">isFormatSupported</code>, <code translate="no" dir="ltr">isGaplessSupported</code>, and <code translate="no" dir="ltr">isSpeedChangeSupported</code>.</li> <li>Add <code translate="no" dir="ltr">AudioSink.setOffloadMode()</code> through which the offload configuration on the audio sink is configured. Default is <code translate="no" dir="ltr">AudioSink.OFFLOAD_MODE_DISABLED</code>.</li> <li>Offload can be enabled through <code translate="no" dir="ltr">setAudioOffloadPreference</code> in <code translate="no" dir="ltr">TrackSelectionParameters</code>. If the set preference is to enable, the device supports offload for the format, and the track selection is a single audio track, then audio offload will be enabled.</li> <li>If <code translate="no" dir="ltr">audioOffloadModePreference</code> is set to <code translate="no" dir="ltr">AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED</code>, then the <code translate="no" dir="ltr">DefaultTrackSelector</code> will only select an audio track and only if that track&#39;s format is supported in offload. If no audio track is supported in offload, then no track will be selected.</li> <li>Disabling gapless support for offload when pre-API level 33 due to playback position issue after track transition.</li> <li>Remove parameter <code translate="no" dir="ltr">enableOffload</code> from <code translate="no" dir="ltr">DefaultRenderersFactory.buildAudioSink</code> method signature.</li> <li>Remove method <code translate="no" dir="ltr">DefaultAudioSink.Builder.setOffloadMode</code>.</li> <li>Remove intdef value <code translate="no" dir="ltr">DefaultAudioSink.OffloadMode.OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED</code>.</li> <li>Add support for Opus gapless metadata during offload playback.</li> <li>Allow renderer recovery by disabling offload if failed at first write (<a href="https://github.com/androidx/media/issues/627">#627</a>).</li> <li>Enable Offload Scheduling by default for audio-only offloaded playback.</li> <li>Delete <code translate="no" dir="ltr">ExoPlayer.experimentalSetOffloadSchedulingEnabled</code> and <code translate="no" dir="ltr">AudioOffloadListener.onExperimentalOffloadSchedulingEnabledChanged</code>.</li> <li>Renamed <code translate="no" dir="ltr">onExperimentalSleepingForOffloadChanged</code> as <code translate="no" dir="ltr">onSleepingForOffloadChanged</code> and <code translate="no" dir="ltr">onExperimentalOffloadedPlayback</code> as <code translate="no" dir="ltr">onOffloadedPlayback</code>.</li> <li>Move audio offload mode related <code translate="no" dir="ltr">TrackSelectionParameters</code> interfaces and definitions to an inner <code translate="no" dir="ltr">AudioOffloadPreferences</code> class.</li> <li>Add <code translate="no" dir="ltr">onAudioTrackInitialized</code> and <code translate="no" dir="ltr">onAudioTrackReleased</code> callbacks to <code translate="no" dir="ltr">AnalyticsListener</code>, <code translate="no" dir="ltr">AudioRendererEventListener</code> and <code translate="no" dir="ltr">AudioSink.Listener</code>.</li> <li>Fix DTS Express audio buffer underflow issue (<a href="https://github.com/androidx/media/pull/650">#650</a>).</li> <li>Fix bug where the capabilities check for E-AC3-JOC throws an <code translate="no" dir="ltr">IllegalArgumentException</code> (<a href="https://github.com/androidx/media/issues/677">#677</a>).</li> </ul></li> <li>Video: <ul> <li>Allow <code translate="no" dir="ltr">MediaCodecVideoRenderer</code> to use a custom <code translate="no" dir="ltr">VideoFrameProcessor.Factory</code>.</li> <li>Fix bug where the first frame couldn&#39;t be rendered if the audio stream starts with negative timestamps (<a href="https://github.com/androidx/media/issues/291">#291</a>).</li> </ul></li> <li>Text: <ul> <li>Remove <code translate="no" dir="ltr">ExoplayerCuesDecoder</code>. Text tracks with <code translate="no" dir="ltr">sampleMimeType = application/x-media3-cues</code> are now directly handled by <code translate="no" dir="ltr">TextRenderer</code> without needing a <code translate="no" dir="ltr">SubtitleDecoder</code> instance.</li> </ul></li> <li>Metadata: <ul> <li><code translate="no" dir="ltr">MetadataDecoder.decode</code> will no longer be called for &quot;decode-only&quot; samples as the implementation must return null anyway.</li> </ul></li> <li>Effect: <ul> <li>Add <code translate="no" dir="ltr">VideoFrameProcessor.queueInputBitmap(Bitmap, Iterator&lt;Long&gt;)</code> queuing bitmap input by timestamp.</li> <li>Change <code translate="no" dir="ltr">VideoFrameProcessor.registerInputStream()</code> to be non-blocking. Apps must implement <code translate="no" dir="ltr">VideoFrameProcessor.Listener#onInputStreamRegistered()</code>.</li> <li>Changed <code translate="no" dir="ltr">frameRate</code> and <code translate="no" dir="ltr">durationUs</code> parameters of <code translate="no" dir="ltr">VideoFrameProcessor.queueInputBitmap</code> to <code translate="no" dir="ltr">TimestampIterator</code>.</li> </ul></li> <li>IMA extension: <ul> <li>Fix bug where a multi-period DASH live stream that is not the first item in a playlist can throw an exception (<a href="https://github.com/androidx/media/issues/571">#571</a>).</li> <li>Release StreamManager before calling <code translate="no" dir="ltr">AdsLoader.destroy()</code></li> <li>Bump IMA SDK version to 3.31.0.</li> </ul></li> <li>Session: <ul> <li>Set the notifications foreground service behavior to <code translate="no" dir="ltr">FOREGROUND_SERVICE_IMMEDIATE</code> in <code translate="no" dir="ltr">DefaultMediaNotificationProvider</code> (<a href="https://github.com/androidx/media/issues/167">#167</a>).</li> <li>Use only <code translate="no" dir="ltr">android.media.session.MediaSession.setMediaButtonBroadcastReceiver()</code> above API 31 to avoid problems with deprecated API on Samsung devices (<a href="https://github.com/androidx/media/issues/167">#167</a>).</li> <li>Use the media notification controller as proxy to set available commands and custom layout used to populate the notification and the platform session.</li> <li>Convert media button events that are received by <code translate="no" dir="ltr">MediaSessionService.onStartCommand()</code> within Media3 instead of routing them to the platform session and back to Media3. With this, the caller controller is always the media notification controller and apps can easily recognize calls coming from the notification in the same way on all supported API levels.</li> <li>Fix bug where <code translate="no" dir="ltr">MediaController.getCurrentPosition()</code> is not advancing when connected to a legacy <code translate="no" dir="ltr">MediaSessionCompat</code>.</li> <li>Add <code translate="no" dir="ltr">MediaLibrarySession.getSubscribedControllers(mediaId)</code> for convenience.</li> <li>Override <code translate="no" dir="ltr">MediaLibrarySession.Callback.onSubscribe()</code> to assert the availability of the parent ID for which the controller subscribes. If successful, the subscription is accepted and <code translate="no" dir="ltr">notifyChildrenChanged()</code> is called immediately to inform the browser (<a href="https://github.com/androidx/media/issues/561">#561</a>).</li> <li>Add session demo module for Automotive OS and enable session demo for Android Auto.</li> <li>Do not set the queue of the framework session when <code translate="no" dir="ltr">COMMAND_GET_TIMELINE</code> is not available for the media notification controller. With Android Auto as the client controller reading from the framework session, this has the effect that the <code translate="no" dir="ltr">queue</code> button in the UI of Android Auto is not displayed (<a href="https://github.com/androidx/media/issues/339">#339</a>).</li> <li>Use <code translate="no" dir="ltr">DataSourceBitmapLoader</code> by default instead of <code translate="no" dir="ltr">SimpleBitmapLoader</code> (<a href="https://github.com/androidx/media/issues/271">#271</a>, <a href="https://github.com/androidx/media/issues/327">#327</a>).</li> <li>Add <code translate="no" dir="ltr">MediaSession.Callback.onMediaButtonEvent(Intent)</code> that allows apps to override the default media button event handling.</li> </ul></li> <li>UI: <ul> <li>Add a <code translate="no" dir="ltr">Player.Listener</code> implementation for Wear OS devices that handles playback suppression due to <code translate="no" dir="ltr">Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT</code> by launching a system dialog to allow a user to connect a suitable audio output (e.g. bluetooth headphones). The listener will auto-resume playback if a suitable device is connected within a configurable timeout (default is 5 minutes).</li> </ul></li> <li>Downloads: <ul> <li>Declare &quot;data sync&quot; foreground service type for <code translate="no" dir="ltr">DownloadService</code> for Android 14 compatibility. When using this service, the app also needs to add <code translate="no" dir="ltr">dataSync</code> as <code translate="no" dir="ltr">foregroundServiceType</code> in the manifest and add the <code translate="no" dir="ltr">FOREGROUND_SERVICE_DATA_SYNC</code> permission (<a href="https://github.com/google/ExoPlayer/issues/11239">#11239</a>).</li> </ul></li> <li>HLS Extension: <ul> <li>Refresh the HLS live playlist with an interval calculated from the last load start time rather than the last load completed time (<a href="https://github.com/androidx/media/issues/663">#663</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Allow multiple of the same DASH identifier in segment template URL.</li> <li>Add experimental support for parsing subtitles during extraction. This has better support for merging overlapping subtitles, including resolving flickering when transitioning between subtitle segments. You can enable this using <code translate="no" dir="ltr">DashMediaSource.Factory.experimentalParseSubtitlesDuringExtraction()</code> (<a href="https://github.com/androidx/media/issues/288">#288</a>).</li> </ul></li> <li>RTSP Extension: <ul> <li>Fix a race condition that could lead to <code translate="no" dir="ltr">IndexOutOfBoundsException</code> when falling back to TCP, or playback hanging in some situations.</li> <li>Check state in RTSP setup when returning loading state of <code translate="no" dir="ltr">RtspMediaPeriod</code> (<a href="https://github.com/androidx/media/issues/577">#577</a>).</li> <li>Ignore custom Rtsp request methods in Options response public header (<a href="https://github.com/androidx/media/issues/613">#613</a>).</li> <li>Use RTSP Setup Response timeout value in time interval of sending keep-alive RTSP Options requests (<a href="https://github.com/androidx/media/issues/662">#662</a>).</li> </ul></li> <li>Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.): <ul> <li>Release the MIDI decoder module, which provides support for playback of standard MIDI files using the Jsyn library to synthesize audio.</li> <li>Add <code translate="no" dir="ltr">DecoderOutputBuffer.shouldBeSkipped</code> to directly mark output buffers that don&#39;t need to be presented. This is preferred over <code translate="no" dir="ltr">C.BUFFER_FLAG_DECODE_ONLY</code> that will be deprecated.</li> <li>Add <code translate="no" dir="ltr">Decoder.setOutputStartTimeUs</code> and <code translate="no" dir="ltr">SimpleDecoder.isAtLeastOutputStartTimeUs</code> to allow decoders to drop decode-only samples before the start time. This should be preferred to <code translate="no" dir="ltr">Buffer.isDecodeOnly</code> that will be deprecated.</li> <li>Fix bug publishing MIDI decoder artifact to Maven repository. The artifact is renamed to <code translate="no" dir="ltr">media3-exoplayer-midi</code> (<a href="https://github.com/androidx/media/issues/734">#734</a>).</li> </ul></li> <li>Leanback extension: <ul> <li>Fix bug where disabling a surface can cause an <code translate="no" dir="ltr">ArithmeticException</code> in Leanback code (<a href="https://github.com/androidx/media/issues/617">#617</a>).</li> </ul></li> <li>Test Utilities: <ul> <li>Make <code translate="no" dir="ltr">TestExoPlayerBuilder</code> and <code translate="no" dir="ltr">FakeClock</code> compatible with Espresso UI tests and Compose UI tests. This fixes a bug where playback advances non-deterministically during Espresso or Compose view interactions.</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">TransformationRequest.Builder.setEnableRequestSdrToneMapping(boolean)</code> and <code translate="no" dir="ltr">TransformationRequest.Builder.experimental_setEnableHdrEditing(boolean)</code>. Use <code translate="no" dir="ltr">Composition.Builder.setHdrMode(int)</code> and pass the <code translate="no" dir="ltr">Composition</code> to <code translate="no" dir="ltr">Transformer.start(Composition, String)</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">DownloadNotificationHelper.buildProgressNotification</code> method, use a non deprecated method that takes a <code translate="no" dir="ltr">notMetRequirements</code> parameter instead.</li> </ul></li> </ul> <h3 id="1.2.0-rc01" data-text="Version 1.2.0-rc01" tabindex="-1">Version 1.2.0-rc01</h3> <p>November 1, 2023</p> <p>Use the 1.2.0 <a href="#1.2.0">stable version</a>.</p> <h3 id="1.2.0-beta01" data-text="Version 1.2.0-beta01" tabindex="-1">Version 1.2.0-beta01</h3> <p>October 19, 2023</p> <p>Use the 1.2.0 <a href="#1.2.0">stable version</a>.</p> <h3 id="1.2.0-alpha02" data-text="Version 1.2.0-alpha02" tabindex="-1">Version 1.2.0-alpha02</h3> <p>September 29, 2023</p> <p>Use the 1.2.0 <a href="#1.2.0">stable version</a>.</p> <h3 id="1.2.0-alpha01" data-text="Version 1.2.0-alpha01" tabindex="-1">Version 1.2.0-alpha01</h3> <p>August 17, 2023</p> <p>Use the 1.2.0 <a href="#1.2.0">stable version</a>.</p> <h2 id="version_110_3" data-text="Version 1.1.0" tabindex="-1">Version 1.1.0</h2> <h3 id="1.1.1" data-text="Version 1.1.1" tabindex="-1">Version 1.1.1</h3> <p>August 16, 2023</p> <ul> <li>Common Library: <ul> <li>Remove accidentally added <code translate="no" dir="ltr">multidex</code> dependency from all modules (<a href="https://github.com/androidx/media/issues/499">#499</a>).</li> </ul></li> <li>ExoPlayer: <ul> <li>Fix issue in <code translate="no" dir="ltr">PlaybackStatsListener</code> where spurious <code translate="no" dir="ltr">PlaybackStats</code> are created after the playlist is cleared.</li> <li>Add additional fields to Common Media Client Data (CMCD) logging: streaming format (sf), stream type (st), version (v), top birate (tb), object duration (d), measured throughput (mtp) and object type (ot) (<a href="https://github.com/google/ExoPlayer/issues/8699">#8699</a>).</li> </ul></li> <li>Audio: <ul> <li>Fix a bug where <code translate="no" dir="ltr">Player.getState()</code> never transitioned to <code translate="no" dir="ltr">STATE_ENDED</code> when playing very short files (<a href="https://github.com/androidx/media/issues/538">#538</a>).</li> </ul></li> <li>Audio Offload: <ul> <li>Prepend Ogg ID Header and Comment Header Pages to bitstream for offloaded Opus playback in accordance with RFC 7845.</li> </ul></li> <li>Video: <ul> <li>H.265/HEVC: Fix parsing SPS short and long term reference picture info.</li> </ul></li> <li>Text: <ul> <li>CEA-608: Change cue truncation logic to only consider visible text. Previously indent and tab offset were included when limiting the cue length to 32 characters (which was technically correct by the spec) (<a href="https://github.com/google/ExoPlayer/issues/11019">#11019</a>).</li> </ul></li> <li>IMA extension: <ul> <li>Bump IMA SDK version to 3.30.3.</li> </ul></li> <li>Session: <ul> <li>Add custom layout to the state of the controller and provide a getter to access it. When the custom layout changes, <code translate="no" dir="ltr">MediaController.Listener.onCustomLayoutChanged</code> is called. Apps that want to send different custom layouts to different Media3 controller can do this in <code translate="no" dir="ltr">MediaSession.Callback.onConnect</code> by using an <code translate="no" dir="ltr">AcceptedResultBuilder</code> to make sure the custom layout is available to the controller when connection completes.</li> <li>Fix cases where <code translate="no" dir="ltr">MediaLibraryServiceLegacyStub</code> sent an error to a <code translate="no" dir="ltr">Result</code> that didn&#39;t support this which produced an <code translate="no" dir="ltr">UnsupportedOperationException</code> (<a href="https://github.com/androidx/media/issues/78">#78</a>).</li> <li>Fix the way <code translate="no" dir="ltr">PlayerWrapper</code> creates a <code translate="no" dir="ltr">VolumeProviderCompat</code> by determining <code translate="no" dir="ltr">volumeControlType</code> through both legacy commands (<code translate="no" dir="ltr">COMMAND_ADJUST_DEVICE_VOLUME</code> and <code translate="no" dir="ltr">COMMAND_SET_DEVICE_VOLUME</code>) and new commands (<code translate="no" dir="ltr">COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS</code> and <code translate="no" dir="ltr">COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS</code>) (<a href="https://github.com/androidx/media/issues/554">#554</a>).</li> </ul></li> </ul> <h3 id="1.1.0" data-text="Version 1.1.0" tabindex="-1">Version 1.1.0</h3> <p>July 5, 2023</p> <ul> <li>Common Library: <ul> <li>Add suppression reason for unsuitable audio route and play when ready change reason for suppressed too long. (<a href="https://github.com/androidx/media/issues/15">#15</a>).</li> <li>Add commands to Player: <ul> <li><code translate="no" dir="ltr">COMMAND_GET_METADATA</code></li> <li><code translate="no" dir="ltr">COMMAND_SET_PLAYLIST_METADATA</code></li> <li><code translate="no" dir="ltr">COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS</code></li> <li><code translate="no" dir="ltr">COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS</code></li> </ul></li> <li>Add overloaded methods to Player which allow users to specify volume flags: <ul> <li><code translate="no" dir="ltr">void setDeviceVolume(int, int)</code></li> <li><code translate="no" dir="ltr">void increaseDeviceVolume(int)</code></li> <li><code translate="no" dir="ltr">void decreaseDeviceVolume(int)</code></li> <li><code translate="no" dir="ltr">void setDeviceMuted(boolean, int)</code></li> </ul></li> <li>Add <code translate="no" dir="ltr">Builder</code> for <code translate="no" dir="ltr">DeviceInfo</code> and deprecate existing constructor.</li> <li>Add <code translate="no" dir="ltr">DeviceInfo.routingControllerId</code> to specify the routing controller ID for remote playbacks.</li> <li>Add <code translate="no" dir="ltr">Player.replaceMediaItem(s)</code> as a shortcut to adding and removing items at the same position (<a href="https://github.com/google/ExoPlayer/issues/8046">#8046</a>).</li> </ul></li> <li>ExoPlayer: <ul> <li>Allow ExoPlayer to have control of device volume methods only if explicitly opted in. Use <code translate="no" dir="ltr">ExoPlayer.Builder.setDeviceVolumeControlEnabled</code> to have access to: <ul> <li><code translate="no" dir="ltr">getDeviceVolume()</code></li> <li><code translate="no" dir="ltr">isDeviceMuted()</code></li> <li><code translate="no" dir="ltr">setDeviceVolume(int)</code> and <code translate="no" dir="ltr">setDeviceVolume(int, int)</code></li> <li><code translate="no" dir="ltr">increaseDeviceVolume(int)</code> and <code translate="no" dir="ltr">increaseDeviceVolume(int, int)</code></li> <li><code translate="no" dir="ltr">decreaseDeviceVolume(int)</code> and <code translate="no" dir="ltr">decreaseDeviceVolume(int, int)</code></li> </ul></li> <li>Add <code translate="no" dir="ltr">FilteringMediaSource</code> that allows to filter available track types from a <code translate="no" dir="ltr">MediaSource</code>.</li> <li>Add support for including Common Media Client Data (CMCD) in the outgoing requests of adaptive streaming formats DASH, HLS, and SmoothStreaming. The following fields, <code translate="no" dir="ltr">br</code>, <code translate="no" dir="ltr">bl</code>, <code translate="no" dir="ltr">cid</code>, <code translate="no" dir="ltr">rtp</code>, and <code translate="no" dir="ltr">sid</code>, have been incorporated (<a href="https://github.com/google/ExoPlayer/issues/8699">#8699</a>). API structure and API methods: <ul> <li>CMCD logging is disabled by default, use <code translate="no" dir="ltr">MediaSource.Factory.setCmcdConfigurationFactory(CmcdConfiguration.Factory cmcdConfigurationFactory)</code> to enable it.</li> <li>All keys are enabled by default, override <code translate="no" dir="ltr">CmcdConfiguration.RequestConfig.isKeyAllowed(String key)</code> to filter out which keys are logged.</li> <li>Override <code translate="no" dir="ltr">CmcdConfiguration.RequestConfig.getCustomData()</code> to enable custom key logging.</li> </ul></li> <li>Add additional action to manifest of main demo to make it easier to start the demo app with a custom <code translate="no" dir="ltr">*.exolist.json</code> file (<a href="https://github.com/androidx/media/pull/439">#439</a>).</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.setVideoEffects()</code> for using <code translate="no" dir="ltr">Effect</code> during video playback.</li> <li>Update <code translate="no" dir="ltr">SampleQueue</code> to store <code translate="no" dir="ltr">sourceId</code> as a <code translate="no" dir="ltr">long</code> rather than an <code translate="no" dir="ltr">int</code>. This changes the signatures of public methods <code translate="no" dir="ltr">SampleQueue.sourceId</code> and <code translate="no" dir="ltr">SampleQueue.peekSourceId</code>.</li> <li>Add parameters to <code translate="no" dir="ltr">LoadControl</code> methods <code translate="no" dir="ltr">shouldStartPlayback</code> and <code translate="no" dir="ltr">onTracksSelected</code> that allow associating these methods with the relevant <code translate="no" dir="ltr">MediaPeriod</code>.</li> <li>Change signature of <code translate="no" dir="ltr">ServerSideAdInsertionMediaSource.setAdPlaybackStates(Map&lt;Object, AdPlaybackState&gt;)</code> by adding a timeline parameter that contains the periods with the UIDs used as keys in the map. This is required to avoid concurrency issues with multi-period live streams.</li> <li>Deprecate <code translate="no" dir="ltr">EventDispatcher.withParameters(int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs)</code> and <code translate="no" dir="ltr">BaseMediaSource.createEventDispatcher(..., long mediaTimeOffsetMs)</code>. The variant of the methods without the <code translate="no" dir="ltr">mediaTimeOffsetUs</code> can be called instead. Note that even for the deprecated variants, the offset is not anymore added to <code translate="no" dir="ltr">startTimeUs</code> and <code translate="no" dir="ltr">endTimeUs</code> of the <code translate="no" dir="ltr">MediaLoadData</code> objects that are dispatched by the dispatcher.</li> <li>Rename <code translate="no" dir="ltr">ExoTrackSelection.blacklist</code> to <code translate="no" dir="ltr">excludeTrack</code> and <code translate="no" dir="ltr">isBlacklisted</code> to <code translate="no" dir="ltr">isTrackExcluded</code>.</li> <li>Fix inconsistent behavior between <code translate="no" dir="ltr">ExoPlayer.setMediaItem(s)</code> and <code translate="no" dir="ltr">addMediaItem(s)</code> when called on an empty playlist.</li> </ul></li> <li>Transformer: <ul> <li>Remove <code translate="no" dir="ltr">Transformer.Builder.setMediaSourceFactory(MediaSource.Factory)</code>. Use <code translate="no" dir="ltr">ExoPlayerAssetLoader.Factory(MediaSource.Factory)</code> and <code translate="no" dir="ltr">Transformer.Builder.setAssetLoaderFactory(AssetLoader.Factory)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">Transformer.startTransformation(MediaItem, ParcelFileDescriptor)</code>.</li> <li>Fix a bug where transformation could get stuck (leading to muxer timeout) if the end of the video stream was signaled at the moment when an input frame was pending processing.</li> <li>Query codecs via <code translate="no" dir="ltr">MediaCodecList</code> instead of using <code translate="no" dir="ltr">findDecoder/EncoderForFormat</code> utilities, to expand support.</li> <li>Remove B-frame configuration in <code translate="no" dir="ltr">DefaultEncoderFactory</code> because it doesn&#39;t work on some devices.</li> </ul></li> <li>Track selection: <ul> <li>Add <code translate="no" dir="ltr">DefaultTrackSelector.Parameters.allowInvalidateSelectionsForRendererCapabilitiesChange</code> which is disabled by default. When enabled, the <code translate="no" dir="ltr">DefaultTrackSelector</code> will trigger a new track selection when the renderer capabilities changed.</li> </ul></li> <li>Extractors: <ul> <li>Ogg: Fix bug when seeking in files with a long duration (<a href="https://github.com/androidx/media/issues/391">#391</a>).</li> <li>FMP4: Fix issue where <code translate="no" dir="ltr">TimestampAdjuster</code> initializes a wrong timestamp offset with metadata sample time from emsg atom (<a href="https://github.com/androidx/media/issues/356">#356</a>).</li> </ul></li> <li>Audio: <ul> <li>Fix bug where some playbacks fail when tunneling is enabled and <code translate="no" dir="ltr">AudioProcessors</code> are active, e.g. for gapless trimming (<a href="https://github.com/google/ExoPlayer/issues/10847">#10847</a>).</li> <li>Encapsulate Opus frames in Ogg packets in direct playbacks (offload).</li> <li>Extrapolate current position during sleep with offload scheduling.</li> <li>Add <code translate="no" dir="ltr">Renderer.release()</code> and <code translate="no" dir="ltr">AudioSink.release()</code> for releasing the resources at the end of player&#39;s lifecycle.</li> <li>Listen to audio capabilities changes in <code translate="no" dir="ltr">DefaultAudioSink</code>. Add a required parameter <code translate="no" dir="ltr">context</code> in the constructor of <code translate="no" dir="ltr">DefaultAudioSink</code>, with which the <code translate="no" dir="ltr">DefaultAudioSink</code> will register as the listener to the <code translate="no" dir="ltr">AudioCapabilitiesReceiver</code> and update its <code translate="no" dir="ltr">audioCapabilities</code> property when informed with a capabilities change.</li> <li>Propagate audio capabilities changes via a new event <code translate="no" dir="ltr">onAudioCapabilitiesChanged</code> in <code translate="no" dir="ltr">AudioSink.Listener</code> interface, and a new interface <code translate="no" dir="ltr">RendererCapabilities.Listener</code> which triggers <code translate="no" dir="ltr">onRendererCapabilitiesChanged</code> events.</li> <li>Add <code translate="no" dir="ltr">ChannelMixingAudioProcessor</code> for applying scaling/mixing to audio channels.</li> <li>Add new int value <code translate="no" dir="ltr">DISCARD_REASON_AUDIO_BYPASS_POSSIBLE</code> to <code translate="no" dir="ltr">DecoderDiscardReasons</code> to discard audio decoder when bypass mode is possible after audio capabilities change.</li> <li>Add direct playback support for DTS Express and DTS:X (<a href="https://github.com/androidx/media/pull/335">#335</a>).</li> </ul></li> <li>Video: <ul> <li>Make <code translate="no" dir="ltr">MediaCodecVideoRenderer</code> report a <code translate="no" dir="ltr">VideoSize</code> with a width and height of 0 when the renderer is disabled. <code translate="no" dir="ltr">Player.Listener.onVideoSizeChanged</code> is called accordingly when <code translate="no" dir="ltr">Player.getVideoSize()</code> changes. With this change, ExoPlayer&#39;s video size with <code translate="no" dir="ltr">MediaCodecVideoRenderer</code> has a width and height of 0 when <code translate="no" dir="ltr">Player.getCurrentTracks</code> does not support video, or the size of the supported video track is not yet determined.</li> </ul></li> <li>DRM: <ul> <li>Reduce the visibility of several internal-only methods on <code translate="no" dir="ltr">DefaultDrmSession</code> that aren&#39;t expected to be called from outside the DRM package: <ul> <li><code translate="no" dir="ltr">void onMediaDrmEvent(int)</code></li> <li><code translate="no" dir="ltr">void provision()</code></li> <li><code translate="no" dir="ltr">void onProvisionCompleted()</code></li> <li><code translate="no" dir="ltr">onProvisionError(Exception, boolean)</code></li> </ul></li> </ul></li> <li>Muxer: <ul> <li>Add a new muxer library which can be used to create an MP4 container file.</li> </ul></li> <li>IMA extension: <ul> <li>Enable multi-period live DASH streams for DAI. Please note that the current implementation does not yet support seeking in live streams (<a href="https://github.com/google/ExoPlayer/issues/10912">#10912</a>).</li> <li>Fix a bug where a new ad group is inserted in live streams because the calculated content position in consecutive timelines varies slightly.</li> </ul></li> <li>Session: <ul> <li>Add helper method <code translate="no" dir="ltr">MediaSession.getControllerForCurrentRequest</code> to obtain information about the controller that is currently calling a<code translate="no" dir="ltr">Player</code> method.</li> <li>Add <code translate="no" dir="ltr">androidx.media3.session.MediaButtonReceiver</code> to enable apps to implement playback resumption with media button events sent by, for example, a Bluetooth headset (<a href="https://github.com/androidx/media/issues/167">#167</a>).</li> <li>Add default implementation to <code translate="no" dir="ltr">MediaSession.Callback.onAddMediaItems</code> to allow requested <code translate="no" dir="ltr">MediaItems</code> to be passed onto <code translate="no" dir="ltr">Player</code> if they have <code translate="no" dir="ltr">LocalConfiguration</code> (e.g. URI) (<a href="https://github.com/androidx/media/issues/282">#282</a>).</li> <li>Add &quot;seek to previous&quot; and &quot;seek to next&quot; command buttons on compact media notification view by default for Android 12 and below (<a href="https://github.com/androidx/media/issues/410">#410</a>).</li> <li>Add default implementation to <code translate="no" dir="ltr">MediaSession.Callback.onAddMediaItems</code> to allow requested <code translate="no" dir="ltr">MediaItems</code> to be passed onto <code translate="no" dir="ltr">Player</code> if they have <code translate="no" dir="ltr">LocalConfiguration</code> (e.g. URI) (<a href="https://github.com/androidx/media/issues/282">#282</a>).</li> <li>Add &quot;seek to previous&quot; and &quot;seek to next&quot; command buttons on compact media notification view by default for Android 12 and below (<a href="https://github.com/androidx/media/issues/410">#410</a>).</li> </ul></li> <li>UI: <ul> <li>Add Util methods <code translate="no" dir="ltr">shouldShowPlayButton</code> and <code translate="no" dir="ltr">handlePlayPauseButtonAction</code> to write custom UI elements with a play/pause button.</li> </ul></li> <li>RTSP Extension: <ul> <li>For MPEG4-LATM, use default profile-level-id value if absent in Describe Response SDP message (<a href="https://github.com/androidx/media/issues/302">#302</a>).</li> <li>Use base Uri for relative path resolution from the RTSP session if present in DESCRIBE response header (<a href="https://github.com/google/ExoPlayer/issues/11160">#11160</a>).</li> </ul></li> <li>DASH Extension: <ul> <li>Remove the media time offset from <code translate="no" dir="ltr">MediaLoadData.startTimeMs</code> and <code translate="no" dir="ltr">MediaLoadData.endTimeMs</code> for multi period DASH streams.</li> <li>Fix a bug where re-preparing a multi-period live Dash media source produced a <code translate="no" dir="ltr">IndexOutOfBoundsException</code> (<a href="https://github.com/google/ExoPlayer/issues/10838">#10838</a>).</li> </ul></li> <li>HLS Extension: <ul> <li>Add <code translate="no" dir="ltr">HlsMediaSource.Factory.setTimestampAdjusterInitializationTimeoutMs(long)</code> to set a timeout for the loading thread to wait for the <code translate="no" dir="ltr">TimestampAdjuster</code> to initialize. If the initialization doesn&#39;t complete before the timeout, a <code translate="no" dir="ltr">PlaybackException</code> is thrown to avoid the playback endless stalling. The timeout is set to zero by default (<a href="https://github.com/androidx/media/issues//323">#323</a>).</li> </ul></li> <li>Test Utilities: <ul> <li>Check for URI scheme case insensitivity in <code translate="no" dir="ltr">DataSourceContractTest</code>.</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">DefaultAudioSink</code> constructors, use <code translate="no" dir="ltr">DefaultAudioSink.Builder</code> instead.</li> <li>Remove <code translate="no" dir="ltr">HlsMasterPlaylist</code>, use <code translate="no" dir="ltr">HlsMultivariantPlaylist</code> instead.</li> <li>Remove <code translate="no" dir="ltr">Player.stop(boolean)</code>. Use <code translate="no" dir="ltr">Player.stop()</code> and <code translate="no" dir="ltr">Player.clearMediaItems()</code> (if <code translate="no" dir="ltr">reset</code> is <code translate="no" dir="ltr">true</code>) instead.</li> <li>Remove two deprecated <code translate="no" dir="ltr">SimpleCache</code> constructors, use a non-deprecated constructor that takes a <code translate="no" dir="ltr">DatabaseProvider</code> instead for better performance.</li> <li>Remove <code translate="no" dir="ltr">DefaultBandwidthMeter</code> constructor, use <code translate="no" dir="ltr">DefaultBandwidthMeter.Builder</code> instead.</li> <li>Remove <code translate="no" dir="ltr">DefaultDrmSessionManager</code> constructors, use <code translate="no" dir="ltr">DefaultDrmSessionManager.Builder</code> instead.</li> <li>Remove two deprecated <code translate="no" dir="ltr">HttpDataSource.InvalidResponseCodeException</code> constructors, use a non-deprecated constructor that accepts additional fields(<code translate="no" dir="ltr">cause</code>, <code translate="no" dir="ltr">responseBody</code>) to enhance error logging.</li> <li>Remove <code translate="no" dir="ltr">DownloadHelper.forProgressive</code>, <code translate="no" dir="ltr">DownloadHelper.forHls</code>, <code translate="no" dir="ltr">DownloadHelper.forDash</code>, and <code translate="no" dir="ltr">DownloadHelper.forSmoothStreaming</code>, use <code translate="no" dir="ltr">DownloadHelper.forMediaItem</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">DownloadService</code> constructor, use a non deprecated constructor that includes the option to provide a <code translate="no" dir="ltr">channelDescriptionResourceId</code> parameter.</li> <li>Remove deprecated String constants for Charsets (<code translate="no" dir="ltr">ASCII_NAME</code>, <code translate="no" dir="ltr">UTF8_NAME</code>, <code translate="no" dir="ltr">ISO88591_NAME</code>, <code translate="no" dir="ltr">UTF16_NAME</code> and <code translate="no" dir="ltr">UTF16LE_NAME</code>), use Kotlin Charsets from the <code translate="no" dir="ltr">kotlin.text</code> package, the <code translate="no" dir="ltr">java.nio.charset.StandardCharsets</code> or the <code translate="no" dir="ltr">com.google.common.base.Charsets</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">WorkManagerScheduler</code> constructor, use a non deprecated constructor that includes the option to provide a <code translate="no" dir="ltr">Context</code> parameter instead.</li> <li>Remove the deprecated methods <code translate="no" dir="ltr">createVideoSampleFormat</code>, <code translate="no" dir="ltr">createAudioSampleFormat</code>, <code translate="no" dir="ltr">createContainerFormat</code>, and <code translate="no" dir="ltr">createSampleFormat</code>, which were used to instantiate the <code translate="no" dir="ltr">Format</code> class. Instead use <code translate="no" dir="ltr">Format.Builder</code> for creating instances of <code translate="no" dir="ltr">Format</code>.</li> <li>Remove the deprecated methods <code translate="no" dir="ltr">copyWithMaxInputSize</code>, <code translate="no" dir="ltr">copyWithSubsampleOffsetUs</code>, <code translate="no" dir="ltr">copyWithLabel</code>, <code translate="no" dir="ltr">copyWithManifestFormatInfo</code>, <code translate="no" dir="ltr">copyWithGaplessInfo</code>, <code translate="no" dir="ltr">copyWithFrameRate</code>, <code translate="no" dir="ltr">copyWithDrmInitData</code>, <code translate="no" dir="ltr">copyWithMetadata</code>, <code translate="no" dir="ltr">copyWithBitrate</code> and <code translate="no" dir="ltr">copyWithVideoSize</code>, use <code translate="no" dir="ltr">Format.buildUpon()</code> and setter methods instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">ExoPlayer.retry()</code>, use <code translate="no" dir="ltr">prepare()</code> instead.</li> <li>Remove deprecated zero-arg <code translate="no" dir="ltr">DefaultTrackSelector</code> constructor, use <code translate="no" dir="ltr">DefaultTrackSelector(Context)</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">OfflineLicenseHelper</code> constructor, use <code translate="no" dir="ltr">OfflineLicenseHelper(DefaultDrmSessionManager, DrmSessionEventListener.EventDispatcher)</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">DownloadManager</code> constructor, use the constructor that takes an <code translate="no" dir="ltr">Executor</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">Cue</code> constructors, use <code translate="no" dir="ltr">Cue.Builder</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">OfflineLicenseHelper</code> constructor, use <code translate="no" dir="ltr">OfflineLicenseHelper(DefaultDrmSessionManager, DrmSessionEventListener.EventDispatcher)</code> instead.</li> <li>Remove four deprecated <code translate="no" dir="ltr">AnalyticsListener</code> methods: <ul> <li><code translate="no" dir="ltr">onDecoderEnabled</code>, use <code translate="no" dir="ltr">onAudioEnabled</code> and/or <code translate="no" dir="ltr">onVideoEnabled</code> instead.</li> <li><code translate="no" dir="ltr">onDecoderInitialized</code>, use <code translate="no" dir="ltr">onAudioDecoderInitialized</code> and/or <code translate="no" dir="ltr">onVideoDecoderInitialized</code> instead.</li> <li><code translate="no" dir="ltr">onDecoderInputFormatChanged</code>, use <code translate="no" dir="ltr">onAudioInputFormatChanged</code> and/or <code translate="no" dir="ltr">onVideoInputFormatChanged</code> instead.</li> <li><code translate="no" dir="ltr">onDecoderDisabled</code>, use <code translate="no" dir="ltr">onAudioDisabled</code> and/or <code translate="no" dir="ltr">onVideoDisabled</code> instead.</li> </ul></li> <li>Remove the deprecated <code translate="no" dir="ltr">Player.Listener.onSeekProcessed</code> and <code translate="no" dir="ltr">AnalyticsListener.onSeekProcessed</code>, use <code translate="no" dir="ltr">onPositionDiscontinuity</code> with <code translate="no" dir="ltr">DISCONTINUITY_REASON_SEEK</code> instead.</li> <li>Remove <code translate="no" dir="ltr">ExoPlayer.setHandleWakeLock(boolean)</code>, use <code translate="no" dir="ltr">setWakeMode(int)</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">DefaultLoadControl.Builder.createDefaultLoadControl()</code>, use <code translate="no" dir="ltr">build()</code> instead.</li> <li>Remove deprecated <code translate="no" dir="ltr">MediaItem.PlaybackProperties</code>, use <code translate="no" dir="ltr">MediaItem.LocalConfiguration</code> instead. Deprecated field <code translate="no" dir="ltr">MediaItem.playbackProperties</code> is now of type <code translate="no" dir="ltr">MediaItem.LocalConfiguration</code>.</li> </ul></li> </ul> <h3 id="1.1.0-rc01" data-text="Version 1.1.0-rc01" tabindex="-1">Version 1.1.0-rc01</h3> <p>June 21, 2023</p> <p>Use the 1.1.0 <a href="#1.1.0">stable version</a>.</p> <h3 id="1.1.0-beta01" data-text="Version 1.1.0-beta01" tabindex="-1">Version 1.1.0-beta01</h3> <p>June 7, 2023</p> <p>Use the 1.1.0 <a href="#1.1.0">stable version</a>.</p> <h3 id="1.1.0-alpha01" data-text="Version 1.1.0-alpha01" tabindex="-1">Version 1.1.0-alpha01</h3> <p>May 10, 2023</p> <p>Use the 1.1.0 <a href="#1.1.0">stable version</a>.</p> <h2 id="version_100_3" data-text="Version 1.0.0" tabindex="-1">Version 1.0.0</h2> <h3 id="1.0.2" data-text="Version 1.0.2" tabindex="-1">Version 1.0.2</h3> <p>May 18, 2023</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.2</code> is released. <a href="https://github.com/androidx/media/commits/1.0.2">Version 1.0.2 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.7">ExoPlayer 2.18.7 release</a>.</p> <p>This release contains the following changes since the <a href="#1.0.1">1.0.1 release</a>:</p> <ul> <li>Core library: <ul> <li>Add <code translate="no" dir="ltr">Buffer.isLastSample()</code> that denotes if <code translate="no" dir="ltr">Buffer</code> contains flag <code translate="no" dir="ltr">C.BUFFER_FLAG_LAST_SAMPLE</code>.</li> <li>Fix issue where last frame may not be rendered if the last sample with frames is dequeued without reading the &#39;end of stream&#39; sample. (<a href="https://github.com/google/ExoPlayer/issues/11079">#11079</a>).</li> </ul></li> <li>Extractors: <ul> <li>Fix parsing of H.265 SPS in MPEG-TS files by re-using the parsing logic already used by RTSP and MP4 extractors (<a href="https://github.com/androidx/media/issues/303">#303</a>).</li> </ul></li> <li>Text: <ul> <li>SSA: Add support for UTF-16 files if they start with a byte order mark (<a href="https://github.com/androidx/media/issues/319">#319</a>).</li> </ul></li> <li>Session: <ul> <li>Fix issue where <code translate="no" dir="ltr">MediaController</code> doesn&#39;t update its available commands when connected to a legacy <code translate="no" dir="ltr">MediaSessionCompat</code> that updates its actions.</li> <li>Fix bug that prevented the <code translate="no" dir="ltr">MediaLibraryService</code> from returning null for a call from System UI to <code translate="no" dir="ltr">Callback.onGetLibraryRoot</code> with <code translate="no" dir="ltr">params.isRecent == true</code> on API 30 (<a href="https://github.com/androidx/media/issues/355">#355</a>).</li> <li>Fix memory leak of <code translate="no" dir="ltr">MediaSessionService</code> or <code translate="no" dir="ltr">MediaLibraryService</code> (<a href="https://github.com/androidx/media/issues/346">#346</a>).</li> <li>Fix bug where a combined <code translate="no" dir="ltr">Timeline</code> and position update in a <code translate="no" dir="ltr">MediaSession</code> may cause a <code translate="no" dir="ltr">MediaController</code> to throw an <code translate="no" dir="ltr">IllegalStateException</code>.</li> </ul></li> </ul> <h3 id="1.0.1" data-text="Version 1.0.1" tabindex="-1">Version 1.0.1</h3> <p>April 18, 2023</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.1</code> is released. <a href="https://github.com/androidx/media/commits/1.0.1">Version 1.0.1 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.6">ExoPlayer 2.18.6 release</a>.</p> <ul> <li>Core library: <ul> <li>Reset target live stream override when seeking to default position (<a href="https://github.com/google/ExoPlayer/pull/11051">#11051</a>).</li> <li>Fix bug where empty sample streams in the media could cause playback to be stuck.</li> </ul></li> <li>Session: <ul> <li>Fix bug where multiple identical queue items published by a legacy <code translate="no" dir="ltr">MediaSessionCompat</code> result in an exception in <code translate="no" dir="ltr">MediaController</code> (<a href="https://github.com/androidx/media/issues/290">#290</a>).</li> <li>Add missing forwarding of <code translate="no" dir="ltr">MediaSession.broadcastCustomCommand</code> to the legacy <code translate="no" dir="ltr">MediaControllerCompat.Callback.onSessionEvent</code> (<a href="https://github.com/androidx/media/issues/293">#293</a>).</li> <li>Fix bug where calling <code translate="no" dir="ltr">MediaSession.setPlayer</code> doesn&#39;t update the available commands.</li> <li>Fix issue that <code translate="no" dir="ltr">TrackSelectionOverride</code> instances sent from a <code translate="no" dir="ltr">MediaController</code> are ignored if they reference a group with <code translate="no" dir="ltr">Format.metadata</code> (<a href="https://github.com/androidx/media/issues/296">#296</a>).</li> <li>Fix issue where <code translate="no" dir="ltr">Player.COMMAND_GET_CURRENT_MEDIA_ITEM</code> needs to be available to access metadata via the legacy <code translate="no" dir="ltr">MediaSessionCompat</code>.</li> <li>Fix issue where <code translate="no" dir="ltr">MediaSession</code> instances on a background thread cause crashes when used in <code translate="no" dir="ltr">MediaSessionService</code> (<a href="https://github.com/androidx/media/issues/318">#318</a>).</li> <li>Fix issue where a media button receiver was declared by the library without the app having intended this (<a href="https://github.com/androidx/media/issues/314">#314</a>).</li> </ul></li> <li>DASH: <ul> <li>Fix handling of empty segment timelines (<a href="https://github.com/google/ExoPlayer/issues/11014">#11014</a>).</li> </ul></li> <li>RTSP: <ul> <li>Retry with TCP if RTSP Setup with UDP fails with RTSP Error 461 UnsupportedTransport (<a href="https://github.com/google/ExoPlayer/issues/11069">#11069</a>).</li> </ul></li> </ul> <h3 id="1.0.0" data-text="Version 1.0.0" tabindex="-1">Version 1.0.0</h3> <p>March 22, 2023</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0">Version 1.0.0 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.5">ExoPlayer 2.18.5 release</a>.</p> <p>There are no changes since 1.0.0-rc02.</p> <h3 id="1.0.0-rc02" data-text="Version 1.0.0-rc02" tabindex="-1">Version 1.0.0-rc02</h3> <p>March 2, 2023</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-rc02</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-rc02">Version 1.0.0-rc02 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.4">ExoPlayer 2.18.4 release</a>.</p> <ul> <li>Core library: <ul> <li>Fix network type detection on API 33 (<a href="https://github.com/google/ExoPlayer/issues/10970">#10970</a>).</li> <li>Fix <code translate="no" dir="ltr">NullPointerException</code> when calling <code translate="no" dir="ltr">ExoPlayer.isTunnelingEnabled</code> (<a href="https://github.com/google/ExoPlayer/issues/10977">#10977</a>).</li> </ul></li> <li>Downloads: <ul> <li>Make the maximum difference of the start time of two segments to be merged configurable in <code translate="no" dir="ltr">SegmentDownloader</code> and subclasses (<a href="https://github.com/androidx/media/pull/248">#248</a>).</li> </ul></li> <li>Audio: <ul> <li>Fix broken gapless MP3 playback on Samsung devices (<a href="https://github.com/google/ExoPlayer/issues/8594">#8594</a>).</li> <li>Fix bug where playback speeds set immediately after disabling audio may be overridden by a previous speed change (<a href="https://github.com/google/ExoPlayer/issues/10882">#10882</a>).</li> </ul></li> <li>Video: <ul> <li>Map HEVC HDR10 format to <code translate="no" dir="ltr">HEVCProfileMain10HDR10</code> instead of <code translate="no" dir="ltr">HEVCProfileMain10</code>.</li> <li>Add workaround for a device issue on Chromecast with Google TV and Lenovo M10 FHD Plus that causes 60fps AVC streams to be marked as unsupported (<a href="https://github.com/google/ExoPlayer/issues/10898">#10898</a>).</li> <li>Fix frame release performance issues when playing media with a frame rate far higher than the screen refresh rate.</li> </ul></li> <li>Cast: <ul> <li>Fix transient <code translate="no" dir="ltr">STATE_IDLE</code> when transitioning between media items (<a href="https://github.com/androidx/media/issues/245">#245</a>).</li> </ul></li> <li>RTSP: <ul> <li>Catch the IllegalArgumentException thrown in parsing of invalid RTSP Describe response messages (<a href="https://github.com/google/ExoPlayer/issues/10971">#10971</a>).</li> </ul></li> <li>Session: <ul> <li>Fix a bug where notification play/pause button doesn&#39;t update with player state (<a href="https://github.com/androidx/media/issues/192">#192</a>).</li> </ul></li> <li>IMA extension: <ul> <li>Fix a bug which prevented DAI streams without any ads from starting because the first (and in the case without ads the only) <code translate="no" dir="ltr">LOADED</code> event wasn&#39;t received.</li> </ul></li> </ul> <h3 id="1.0.0-rc01" data-text="Version 1.0.0-rc01" tabindex="-1">Version 1.0.0-rc01</h3> <p>February 16, 2023</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-rc01</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-rc01">Version 1.0.0-rc01 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.3">ExoPlayer 2.18.3 release</a>.</p> <ul> <li>Core library: <ul> <li>Tweak the renderer&#39;s decoder ordering logic to uphold the <code translate="no" dir="ltr">MediaCodecSelector</code>&#39;s preferences, even if a decoder reports it may not be able to play the media performantly. For example with default selector, hardware decoder with only functional support will be preferred over software decoder that fully supports the format (<a href="https://github.com/google/ExoPlayer/issues/10604">#10604</a>).</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.Builder.setPlaybackLooper</code> that sets a pre-existing playback thread for a new ExoPlayer instance.</li> <li>Allow download manager helpers to be cleared (<a href="https://github.com/google/ExoPlayer/issues/10776">#10776</a>).</li> <li>Add parameter to <code translate="no" dir="ltr">BasePlayer.seekTo</code> to also indicate the command used for seeking.</li> <li>Use theme when loading drawables on API 21+ (<a href="https://github.com/androidx/media/issues/220">#220</a>).</li> <li>Add <code translate="no" dir="ltr">ConcatenatingMediaSource2</code> that allows combining multiple media items into a single window (<a href="https://github.com/androidx/media/issues/247">#247</a>).</li> </ul></li> <li>Extractors: <ul> <li>Throw a <code translate="no" dir="ltr">ParserException</code> instead of a <code translate="no" dir="ltr">NullPointerException</code> if the sample table (stbl) is missing a required sample description (stsd) when parsing trak atoms.</li> <li>Correctly skip samples when seeking directly to a sync frame in fMP4 (<a href="https://github.com/google/ExoPlayer/issues/10941">#10941</a>).</li> </ul></li> <li>Audio: <ul> <li>Use the compressed audio format bitrate to calculate the min buffer size for <code translate="no" dir="ltr">AudioTrack</code> in direct playbacks (passthrough).</li> </ul></li> <li>Text: <ul> <li>Fix <code translate="no" dir="ltr">TextRenderer</code> passing an invalid (negative) index to <code translate="no" dir="ltr">Subtitle.getEventTime</code> if a subtitle file contains no cues.</li> <li>SubRip: Add support for UTF-16 files if they start with a byte order mark.</li> </ul></li> <li>Metadata: <ul> <li>Parse multiple null-separated values from ID3 frames, as permitted by ID3 v2.4.</li> <li>Add <code translate="no" dir="ltr">MediaMetadata.mediaType</code> to denote the type of content or the type of folder described by the metadata.</li> <li>Add <code translate="no" dir="ltr">MediaMetadata.isBrowsable</code> as a replacement for <code translate="no" dir="ltr">MediaMetadata.folderType</code>. The folder type will be deprecated in the next release.</li> </ul></li> <li>DASH: <ul> <li>Add full parsing for image adaptation sets, including tile counts (<a href="https://github.com/google/ExoPlayer/issues/3752">#3752</a>).</li> </ul></li> <li>UI: <ul> <li>Fix the deprecated <code translate="no" dir="ltr">PlayerView.setControllerVisibilityListener(PlayerControlView.VisibilityListener)</code> to ensure visibility changes are passed to the registered listener (<a href="https://github.com/androidx/media/issues/229">#229</a>).</li> <li>Fix the ordering of the center player controls in <code translate="no" dir="ltr">PlayerView</code> when using a right-to-left (RTL) layout (<a href="https://github.com/androidx/media/issues/227">#227</a>).</li> </ul></li> <li>Session: <ul> <li>Add abstract <code translate="no" dir="ltr">SimpleBasePlayer</code> to help implement the <code translate="no" dir="ltr">Player</code> interface for custom players.</li> <li>Add helper method to convert platform session token to Media3 <code translate="no" dir="ltr">SessionToken</code> (<a href="https://github.com/androidx/media/issues/171">#171</a>).</li> <li>Use <code translate="no" dir="ltr">onMediaMetadataChanged</code> to trigger updates of the platform media session (<a href="https://github.com/androidx/media/issues/219">#219</a>).</li> <li>Add the media session as an argument of <code translate="no" dir="ltr">getMediaButtons()</code> of the <code translate="no" dir="ltr">DefaultMediaNotificationProvider</code> and use immutable lists for clarity (<a href="https://github.com/androidx/media/issues/216">#216</a>).</li> <li>Add <code translate="no" dir="ltr">onSetMediaItems</code> callback listener to provide means to modify/set <code translate="no" dir="ltr">MediaItem</code> list, starting index and position by session before setting onto Player (<a href="https://github.com/androidx/media/issues/156">#156</a>).</li> <li>Avoid double tap detection for non-Bluetooth media button events (<a href="https://github.com/androidx/media/issues/233">#233</a>).</li> <li>Make <code translate="no" dir="ltr">QueueTimeline</code> more robust in case of a shady legacy session state (<a href="https://github.com/androidx/media/issues/241">#241</a>).</li> </ul></li> <li>Metadata: <ul> <li>Parse multiple null-separated values from ID3 frames, as permitted by ID3 v2.4.</li> <li>Add <code translate="no" dir="ltr">MediaMetadata.mediaType</code> to denote the type of content or the type of folder described by the metadata.</li> <li>Add <code translate="no" dir="ltr">MediaMetadata.isBrowsable</code> as a replacement for <code translate="no" dir="ltr">MediaMetadata.folderType</code>. The folder type will be deprecated in the next release.</li> </ul></li> <li>Cast extension: <ul> <li>Bump Cast SDK version to 21.2.0.</li> </ul></li> <li>IMA extension: <ul> <li>Remove player listener of the <code translate="no" dir="ltr">ImaServerSideAdInsertionMediaSource</code> on the application thread to avoid threading issues.</li> <li>Add a property <code translate="no" dir="ltr">focusSkipButtonWhenAvailable</code> to the <code translate="no" dir="ltr">ImaServerSideAdInsertionMediaSource.AdsLoader.Builder</code> to request focusing the skip button on TV devices and set it to true by default.</li> <li>Add a method <code translate="no" dir="ltr">focusSkipButton()</code> to the <code translate="no" dir="ltr">ImaServerSideAdInsertionMediaSource.AdsLoader</code> to programmatically request to focus the skip button.</li> <li>Bump IMA SDK version to 3.29.0.</li> </ul></li> <li>Demo app: <ul> <li>Request notification permission for download notifications at runtime (<a href="https://github.com/google/ExoPlayer/issues/10884">#10884</a>).</li> </ul></li> </ul> <h3 id="1.0.0-beta03" data-text="Version 1.0.0-beta03" tabindex="-1">Version 1.0.0-beta03</h3> <p>November 22, 2022</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-beta03</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-beta03">Version 1.0.0-beta03 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.2">ExoPlayer 2.18.2 release</a>.</p> <ul> <li>Core library: <ul> <li>Add <code translate="no" dir="ltr">ExoPlayer.isTunnelingEnabled</code> to check if tunneling is enabled for the currently selected tracks (<a href="https://github.com/google/ExoPlayer/issues/2518">#2518</a>).</li> <li>Add <code translate="no" dir="ltr">WrappingMediaSource</code> to simplify wrapping a single <code translate="no" dir="ltr">MediaSource</code> (<a href="https://github.com/google/ExoPlayer/issues/7279">#7279</a>).</li> <li>Discard back buffer before playback gets stuck due to insufficient available memory.</li> <li>Close the Tracing &quot;doSomeWork&quot; block when offload is enabled.</li> <li>Fix session tracking problem with fast seeks in <code translate="no" dir="ltr">PlaybackStatsListener</code> (<a href="https://github.com/androidx/media/issues/180">#180</a>).</li> <li>Send missing <code translate="no" dir="ltr">onMediaItemTransition</code> callback when calling <code translate="no" dir="ltr">seekToNext</code> or <code translate="no" dir="ltr">seekToPrevious</code> in a single-item playlist (<a href="https://github.com/google/ExoPlayer/issues/10667">#10667</a>).</li> <li>Add <code translate="no" dir="ltr">Player.getSurfaceSize</code> that returns the size of the surface on which the video is rendered.</li> <li>Fix bug where removing listeners during the player release can cause an <code translate="no" dir="ltr">IllegalStateException</code> (<a href="https://github.com/google/ExoPlayer/issues/10758">#10758</a>).</li> </ul></li> <li>Build: <ul> <li>Enforce minimum <code translate="no" dir="ltr">compileSdkVersion</code> to avoid compilation errors (<a href="https://github.com/google/ExoPlayer/issues/10684">#10684</a>).</li> <li>Avoid publishing block when included in another gradle build.</li> </ul></li> <li>Track selection: <ul> <li>Prefer other tracks to Dolby Vision if display does not support it. (<a href="https://github.com/google/ExoPlayer/issues/8944">#8944</a>).</li> </ul></li> <li>Downloads: <ul> <li>Fix potential infinite loop in <code translate="no" dir="ltr">ProgressiveDownloader</code> caused by simultaneous download and playback with the same <code translate="no" dir="ltr">PriorityTaskManager</code> (<a href="https://github.com/google/ExoPlayer/pull/10570">#10570</a>).</li> <li>Make download notification appear immediately (<a href="https://github.com/androidx/media/pull/183">#183</a>).</li> <li>Limit parallel download removals to 1 to avoid excessive thread creation (<a href="https://github.com/google/ExoPlayer/issues/10458">#10458</a>).</li> </ul></li> <li>Video: <ul> <li>Try alternative decoder for Dolby Vision if display does not support it. (<a href="https://github.com/google/ExoPlayer/issues/9794">#9794</a>).</li> </ul></li> <li>Audio: <ul> <li>Use <code translate="no" dir="ltr">SingleThreadExecutor</code> for releasing <code translate="no" dir="ltr">AudioTrack</code> instances to avoid OutOfMemory errors when releasing multiple players at the same time (<a href="https://github.com/google/ExoPlayer/issues/10057">#10057</a>).</li> <li>Adds <code translate="no" dir="ltr">AudioOffloadListener.onExperimentalOffloadedPlayback</code> for the AudioTrack offload state. (<a href="https://github.com/androidx/media/issues/134">#134</a>).</li> <li>Make <code translate="no" dir="ltr">AudioTrackBufferSizeProvider</code> a public interface.</li> <li>Add <code translate="no" dir="ltr">ExoPlayer.setPreferredAudioDevice</code> to set the preferred audio output device (<a href="https://github.com/androidx/media/issues/135">#135</a>).</li> <li>Rename <code translate="no" dir="ltr">androidx.media3.exoplayer.audio.AudioProcessor</code> to <code translate="no" dir="ltr">androidx.media3.common.audio.AudioProcessor</code>.</li> <li>Map 8-channel and 12-channel audio to the 7.1 and 7.1.4 channel masks respectively on all Android versions (<a href="https://github.com/google/ExoPlayer/issues/10701">#10701</a>).</li> </ul></li> <li>Metadata: <ul> <li><code translate="no" dir="ltr">MetadataRenderer</code> can now be configured to render metadata as soon as they are available. Create an instance with <code translate="no" dir="ltr">MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory, boolean)</code> to specify whether the renderer will output metadata early or in sync with the player position.</li> </ul></li> <li>DRM: <ul> <li>Work around a bug in the Android 13 ClearKey implementation that returns a non-empty but invalid license URL.</li> <li>Fix <code translate="no" dir="ltr">setMediaDrmSession failed: session not opened</code> error when switching between DRM schemes in a playlist (e.g. Widevine to ClearKey).</li> </ul></li> <li>Text: <ul> <li>CEA-608: Ensure service switch commands on field 2 are handled correctly (<a href="https://github.com/google/ExoPlayer/issues/10666">#10666</a>).</li> </ul></li> <li>DASH: <ul> <li>Parse <code translate="no" dir="ltr">EventStream.presentationTimeOffset</code> from manifests (<a href="https://github.com/google/ExoPlayer/issues/10460">#10460</a>).</li> </ul></li> <li>UI: <ul> <li>Use current overrides of the player as preset in <code translate="no" dir="ltr">TrackSelectionDialogBuilder</code> (<a href="https://github.com/google/ExoPlayer/issues/10429">#10429</a>).</li> </ul></li> <li>Session: <ul> <li>Ensure commands are always executed in the correct order even if some require asynchronous resolution (<a href="https://github.com/androidx/media/issues/85">#85</a>).</li> <li>Add <code translate="no" dir="ltr">DefaultMediaNotificationProvider.Builder</code> to build <code translate="no" dir="ltr">DefaultMediaNotificationProvider</code> instances. The builder can configure the notification ID, the notification channel ID and the notification channel name used by the provider. Also, add method <code translate="no" dir="ltr">DefaultMediaNotificationProvider.setSmallIcon(int)</code> to set the notifications small icon. (<a href="https://github.com/androidx/media/issues/104">#104</a>).</li> <li>Ensure commands sent before <code translate="no" dir="ltr">MediaController.release()</code> are not dropped (<a href="https://github.com/androidx/media/issues/99">#99</a>).</li> <li><code translate="no" dir="ltr">SimpleBitmapLoader</code> can load bitmap from <code translate="no" dir="ltr">file://</code> URIs (<a href="https://github.com/androidx/media/issues/108">#108</a>).</li> <li>Fix assertion that prevents <code translate="no" dir="ltr">MediaController</code> to seek over an ad in a period (<a href="https://github.com/androidx/media/issues/122">#122</a>).</li> <li>When playback ends, the <code translate="no" dir="ltr">MediaSessionService</code> is stopped from the foreground and a notification is shown to restart playback of the last played media item (<a href="https://github.com/androidx/media/issues/112">#112</a>).</li> <li>Don&#39;t start a foreground service with a pending intent for pause (<a href="https://github.com/androidx/media/issues/167">#167</a>).</li> <li>Manually hide the &#39;badge&#39; associated with the notification created by <code translate="no" dir="ltr">DefaultNotificationProvider</code> on API 26 and API 27 (the badge is automatically hidden on API 28+) (<a href="https://github.com/androidx/media/issues/131">#131</a>).</li> <li>Fix bug where a second binder connection from a legacy MediaSession to a Media3 MediaController causes IllegalStateExceptions (<a href="https://github.com/androidx/media/issues/49">#49</a>).</li> </ul></li> <li>RTSP: <ul> <li>Add H263 fragmented packet handling (<a href="https://github.com/androidx/media/pull/119">#119</a>).</li> <li>Add support for MP4A-LATM (<a href="https://github.com/androidx/media/pull/162">#162</a>).</li> </ul></li> <li>IMA: <ul> <li>Add timeout for loading ad information to handle cases where the IMA SDK gets stuck loading an ad (<a href="https://github.com/google/ExoPlayer/issues/10510">#10510</a>).</li> <li>Prevent skipping mid-roll ads when seeking to the end of the content (<a href="https://github.com/google/ExoPlayer/issues/10685">#10685</a>).</li> <li>Correctly calculate window duration for live streams with server-side inserted ads, for example IMA DAI (<a href="https://github.com/google/ExoPlayer/issues/10764">#10764</a>).</li> </ul></li> <li>FFmpeg extension: <ul> <li>Add newly required flags to link FFmpeg libraries with NDK 23.1.7779620 and above (<a href="https://github.com/google/ExoPlayer/issues/9933">#9933</a>).</li> </ul></li> <li>AV1 extension: <ul> <li>Update CMake version to avoid incompatibilities with the latest Android Studio releases (<a href="https://github.com/google/ExoPlayer/issues/9933">#9933</a>).</li> </ul></li> <li>Cast extension: <ul> <li>Implement <code translate="no" dir="ltr">getDeviceInfo()</code> to be able to identify <code translate="no" dir="ltr">CastPlayer</code> when controlling playback with a <code translate="no" dir="ltr">MediaController</code> (<a href="https://github.com/androidx/media/issues/142">#142</a>).</li> </ul></li> <li>Transformer: <ul> <li>Add muxer watchdog timer to detect when generating an output sample is too slow.</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">Transformer.Builder.setOutputMimeType(String)</code>. This feature has been removed. The MIME type will always be MP4 when the default muxer is used.</li> </ul></li> </ul> <h3 id="1.0.0-beta02" data-text="Version 1.0.0-beta02" tabindex="-1">Version 1.0.0-beta02</h3> <p>July 21, 2022</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-beta02</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-beta02">Version 1.0.0-beta02 contains these commits.</a></p> <p>This release corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.1">ExoPlayer 2.18.1 release</a>.</p> <ul> <li>Core library: <ul> <li>Ensure that changing the <code translate="no" dir="ltr">ShuffleOrder</code> with <code translate="no" dir="ltr">ExoPlayer.setShuffleOrder</code> results in a call to <code translate="no" dir="ltr">Player.Listener#onTimelineChanged</code> with <code translate="no" dir="ltr">reason=Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED</code> (<a href="https://github.com/google/ExoPlayer/issues/9889">#9889</a>).</li> <li>For progressive media, only include selected tracks in buffered position (<a href="https://github.com/google/ExoPlayer/issues/10361">#10361</a>).</li> <li>Allow custom logger for all ExoPlayer log output (<a href="https://github.com/google/ExoPlayer/issues/9752">#9752</a>).</li> <li>Fix implementation of <code translate="no" dir="ltr">setDataSourceFactory</code> in <code translate="no" dir="ltr">DefaultMediaSourceFactory</code>, which was non-functional in some cases (<a href="https://github.com/androidx/media/issues/116">#116</a>).</li> </ul></li> <li>Extractors: <ul> <li>Fix parsing of H265 short term reference picture sets (<a href="https://github.com/google/ExoPlayer/issues/10316">#10316</a>).</li> <li>Fix parsing of bitrates from <code translate="no" dir="ltr">esds</code> boxes (<a href="https://github.com/google/ExoPlayer/issues/10381">#10381</a>).</li> </ul></li> <li>DASH: <ul> <li>Parse ClearKey license URL from manifests (<a href="https://github.com/google/ExoPlayer/issues/10246">#10246</a>).</li> </ul></li> <li>UI: <ul> <li>Ensure TalkBack announces the currently active speed option in the playback controls menu (<a href="https://github.com/google/ExoPlayer/issues/10298">#10298</a>).</li> </ul></li> <li>RTSP: <ul> <li>Add VP8 fragmented packet handling (<a href="https://github.com/androidx/media/pull/110">#110</a>).</li> </ul></li> <li>Leanback extension: <ul> <li>Listen to <code translate="no" dir="ltr">playWhenReady</code> changes in <code translate="no" dir="ltr">LeanbackAdapter</code> (<a href="https://github.com/google/ExoPlayer/issues/10420">10420</a>).</li> </ul></li> <li>Cast: <ul> <li>Use the <code translate="no" dir="ltr">MediaItem</code> that has been passed to the playlist methods as <code translate="no" dir="ltr">Window.mediaItem</code> in <code translate="no" dir="ltr">CastTimeline</code> (<a href="https://github.com/androidx/media/issues/25">#25</a>, <a href="https://github.com/google/ExoPlayer/issues/8212">#8212</a>).</li> <li>Support <code translate="no" dir="ltr">Player.getMetadata()</code> and <code translate="no" dir="ltr">Listener.onMediaMetadataChanged()</code> with <code translate="no" dir="ltr">CastPlayer</code> (<a href="https://github.com/androidx/media/issues/25">#25</a>).</li> </ul></li> </ul> <h3 id="1.0.0-beta01" data-text="Version 1.0.0-beta01" tabindex="-1">Version 1.0.0-beta01</h3> <p>June 16, 2022</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-beta01</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-beta01">Version 1.0.0-beta01 contains these commits.</a></p> <p>This corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.18.0">ExoPlayer 2.18.0 release</a>.</p> <ul> <li>Core library: <ul> <li>Enable support for Android platform diagnostics via <code translate="no" dir="ltr">MediaMetricsManager</code>. ExoPlayer will forward playback events and performance data to the platform, which helps to provide system performance and debugging information on the device. This data may also be collected by Google <a href="https://support.google.com/accounts/answer/6078260">if sharing usage and diagnostics data is enabled</a> by the user of the device. Apps can opt-out of contributing to platform diagnostics for ExoPlayer with <code translate="no" dir="ltr">ExoPlayer.Builder.setUsePlatformDiagnostics(false)</code>.</li> <li>Fix bug that tracks are reset too often when using <code translate="no" dir="ltr">MergingMediaSource</code>, for example when side-loading subtitles and changing the selected subtitle mid-playback (<a href="https://github.com/google/ExoPlayer/issues/10248">#10248</a>).</li> <li>Stop detecting 5G-NSA network type on API 29 and 30. These playbacks will assume a 4G network.</li> <li>Disallow passing <code translate="no" dir="ltr">null</code> to <code translate="no" dir="ltr">MediaSource.Factory.setDrmSessionManagerProvider</code> and <code translate="no" dir="ltr">MediaSource.Factory.setLoadErrorHandlingPolicy</code>. Instances of <code translate="no" dir="ltr">DefaultDrmSessionManagerProvider</code> and <code translate="no" dir="ltr">DefaultLoadErrorHandlingPolicy</code> can be passed explicitly if required.</li> <li>Add <code translate="no" dir="ltr">MediaItem.RequestMetadata</code> to represent metadata needed to play media when the exact <code translate="no" dir="ltr">LocalConfiguration</code> is not known. Also remove <code translate="no" dir="ltr">MediaMetadata.mediaUrl</code> as this is now included in <code translate="no" dir="ltr">RequestMetadata</code>.</li> <li>Add <code translate="no" dir="ltr">Player.Command.COMMAND_SET_MEDIA_ITEM</code> to enable players to allow setting a single item.</li> </ul></li> <li>Track selection: <ul> <li>Flatten <code translate="no" dir="ltr">TrackSelectionOverrides</code> class into <code translate="no" dir="ltr">TrackSelectionParameters</code>, and promote <code translate="no" dir="ltr">TrackSelectionOverride</code> to a top level class.</li> <li>Rename <code translate="no" dir="ltr">TracksInfo</code> to <code translate="no" dir="ltr">Tracks</code> and <code translate="no" dir="ltr">TracksInfo.TrackGroupInfo</code> to <code translate="no" dir="ltr">Tracks.Group</code>. <code translate="no" dir="ltr">Player.getCurrentTracksInfo</code> and <code translate="no" dir="ltr">Player.Listener.onTracksInfoChanged</code> have also been renamed to <code translate="no" dir="ltr">Player.getCurrentTracks</code> and <code translate="no" dir="ltr">Player.Listener.onTracksChanged</code>. This includes &#39;un-deprecating&#39; the <code translate="no" dir="ltr">Player.Listener.onTracksChanged</code> method name, but with different parameter types.</li> <li>Change <code translate="no" dir="ltr">DefaultTrackSelector.buildUponParameters</code> and <code translate="no" dir="ltr">DefaultTrackSelector.Parameters.buildUpon</code> to return <code translate="no" dir="ltr">DefaultTrackSelector.Parameters.Builder</code> instead of the deprecated <code translate="no" dir="ltr">DefaultTrackSelector.ParametersBuilder</code>.</li> <li>Add <code translate="no" dir="ltr">DefaultTrackSelector.Parameters.constrainAudioChannelCountToDeviceCapabilities</code> which is enabled by default. When enabled, the <code translate="no" dir="ltr">DefaultTrackSelector</code> will prefer audio tracks whose channel count does not exceed the device output capabilities. On handheld devices, the <code translate="no" dir="ltr">DefaultTrackSelector</code> will prefer stereo/mono over multichannel audio formats, unless the multichannel format can be <a href="https://developer.android.com/reference/android/media/Spatializer">Spatialized</a> (Android 12L+) or is a Dolby surround sound format. In addition, on devices that support audio spatialization, the <code translate="no" dir="ltr">DefaultTrackSelector</code> will monitor for changes in the <a href="https://developer.android.com/reference/android/media/Spatializer.OnSpatializerStateChangedListener">Spatializer properties</a> and trigger a new track selection upon these. Devices with a <code translate="no" dir="ltr">television</code> <a href="https://developer.android.com/guide/topics/resources/providing-resources#UiModeQualifier">UI mode</a> are excluded from these constraints and the format with the highest channel count will be preferred. To enable this feature, the <code translate="no" dir="ltr">DefaultTrackSelector</code> instance must be constructed with a <code translate="no" dir="ltr">Context</code>.</li> </ul></li> <li>Video: <ul> <li>Rename <code translate="no" dir="ltr">DummySurface</code> to <code translate="no" dir="ltr">PlaceholderSurface</code>.</li> <li>Add AV1 support to the <code translate="no" dir="ltr">MediaCodecVideoRenderer.getCodecMaxInputSize</code>.</li> </ul></li> <li>Audio: <ul> <li>Use LG AC3 audio decoder advertising non-standard MIME type.</li> <li>Change the return type of <code translate="no" dir="ltr">AudioAttributes.getAudioAttributesV21()</code> from <code translate="no" dir="ltr">android.media.AudioAttributes</code> to a new <code translate="no" dir="ltr">AudioAttributesV21</code> wrapper class, to prevent slow ART verification on API &lt; 21.</li> <li>Query the platform (API 29+) or assume the audio encoding channel count for audio passthrough when the format audio channel count is unset, which occurs with HLS chunkless preparation (<a href="https://github.com/google/ExoPlayer/issues/10204">10204</a>).</li> <li>Configure <code translate="no" dir="ltr">AudioTrack</code> with channel mask <code translate="no" dir="ltr">AudioFormat.CHANNEL_OUT_7POINT1POINT4</code> if the decoder outputs 12 channel PCM audio (<a href="#https://github.com/google/ExoPlayer/pull/10322">#10322</a>.</li> </ul></li> <li>DRM <ul> <li>Ensure the DRM session is always correctly updated when seeking immediately after a format change (<a href="https://github.com/google/ExoPlayer/issues/10274">10274</a>).</li> </ul></li> <li>Text: <ul> <li>Change <code translate="no" dir="ltr">Player.getCurrentCues()</code> to return <code translate="no" dir="ltr">CueGroup</code> instead of <code translate="no" dir="ltr">List&lt;Cue&gt;</code>.</li> <li>SSA: Support <code translate="no" dir="ltr">OutlineColour</code> style setting when <code translate="no" dir="ltr">BorderStyle == 3</code> (i.e. <code translate="no" dir="ltr">OutlineColour</code> sets the background of the cue) (<a href="https://github.com/google/ExoPlayer/issues/8435">#8435</a>).</li> <li>CEA-708: Parse data into multiple service blocks and ignore blocks not associated with the currently selected service number.</li> <li>Remove <code translate="no" dir="ltr">RawCcExtractor</code>, which was only used to handle a Google-internal subtitle format.</li> </ul></li> <li>Extractors: <ul> <li>Add support for AVI (<a href="https://github.com/google/ExoPlayer/issues/2092">#2092</a>).</li> <li>Matroska: Parse <code translate="no" dir="ltr">DiscardPadding</code> for Opus tracks.</li> <li>MP4: Parse bitrates from <code translate="no" dir="ltr">esds</code> boxes.</li> <li>Ogg: Allow duplicate Opus ID and comment headers (<a href="https://github.com/google/ExoPlayer/issues/10038">#10038</a>).</li> </ul></li> <li>UI: <ul> <li>Fix delivery of events to <code translate="no" dir="ltr">OnClickListener</code>s set on <code translate="no" dir="ltr">PlayerView</code> in the case that <code translate="no" dir="ltr">useController=false</code> (<a href="https://github.com/google/ExoPlayer/issues/9605">#9605</a>). Also fix delivery of events to <code translate="no" dir="ltr">OnLongClickListener</code> for all view configurations.</li> <li>Fix incorrectly treating a sequence of touch events that exit the bounds of <code translate="no" dir="ltr">PlayerView</code> before <code translate="no" dir="ltr">ACTION_UP</code> as a click (<a href="https://github.com/google/ExoPlayer/issues/9861">#9861</a>).</li> <li>Fix <code translate="no" dir="ltr">PlayerView</code> accessibility issue where tapping might toggle playback rather than hiding the controls (<a href="https://github.com/google/ExoPlayer/issues/8627">#8627</a>).</li> <li>Rewrite <code translate="no" dir="ltr">TrackSelectionView</code> and <code translate="no" dir="ltr">TrackSelectionDialogBuilder</code> to work with the <code translate="no" dir="ltr">Player</code> interface rather than <code translate="no" dir="ltr">ExoPlayer</code>. This allows the views to be used with other <code translate="no" dir="ltr">Player</code> implementations, and removes the dependency from the UI module to the ExoPlayer module. This is a breaking change.</li> <li>Don&#39;t show forced text tracks in the <code translate="no" dir="ltr">PlayerView</code> track selector, and keep a suitable forced text track selected if &quot;None&quot; is selected (<a href="https://github.com/google/ExoPlayer/issues/9432">#9432</a>).</li> </ul></li> <li>DASH: <ul> <li>Parse channel count from DTS <code translate="no" dir="ltr">AudioChannelConfiguration</code> elements. This re-enables audio passthrough for DTS streams (<a href="https://github.com/google/ExoPlayer/issues/10159">#10159</a>).</li> <li>Disallow passing <code translate="no" dir="ltr">null</code> to <code translate="no" dir="ltr">DashMediaSource.Factory.setCompositeSequenceableLoaderFactory</code>. Instances of <code translate="no" dir="ltr">DefaultCompositeSequenceableLoaderFactory</code> can be passed explicitly if required.</li> </ul></li> <li>HLS: <ul> <li>Fallback to chunkful preparation if the playlist CODECS attribute does not contain the audio codec (<a href="https://github.com/google/ExoPlayer/issues/10065">#10065</a>).</li> <li>Disallow passing <code translate="no" dir="ltr">null</code> to <code translate="no" dir="ltr">HlsMediaSource.Factory.setCompositeSequenceableLoaderFactory</code>, <code translate="no" dir="ltr">HlsMediaSource.Factory.setPlaylistParserFactory</code>, and <code translate="no" dir="ltr">HlsMediaSource.Factory.setPlaylistTrackerFactory</code>. Instances of <code translate="no" dir="ltr">DefaultCompositeSequenceableLoaderFactory</code>, <code translate="no" dir="ltr">DefaultHlsPlaylistParserFactory</code>, or a reference to <code translate="no" dir="ltr">DefaultHlsPlaylistTracker.FACTORY</code> can be passed explicitly if required.</li> </ul></li> <li>Smooth Streaming: <ul> <li>Disallow passing <code translate="no" dir="ltr">null</code> to <code translate="no" dir="ltr">SsMediaSource.Factory.setCompositeSequenceableLoaderFactory</code>. Instances of <code translate="no" dir="ltr">DefaultCompositeSequenceableLoaderFactory</code> can be passed explicitly if required.</li> </ul></li> <li>RTSP: <ul> <li>Add RTP reader for H263 (<a href="https://github.com/androidx/media/pull/63">#63</a>).</li> <li>Add RTP reader for MPEG4 (<a href="https://github.com/androidx/media/pull/35">#35</a>).</li> <li>Add RTP reader for HEVC (<a href="https://github.com/androidx/media/pull/36">#36</a>).</li> <li>Add RTP reader for AMR. Currently only mono-channel, non-interleaved AMR streams are supported. Compound AMR RTP payload is not supported. (<a href="https://github.com/androidx/media/pull/46">#46</a>)</li> <li>Add RTP reader for VP8 (<a href="https://github.com/androidx/media/pull/47">#47</a>).</li> <li>Add RTP reader for WAV (<a href="https://github.com/androidx/media/pull/56">#56</a>).</li> <li>Fix RTSP basic authorization header. (<a href="https://github.com/google/ExoPlayer/issues/9544">#9544</a>).</li> <li>Stop checking mandatory SDP fields as ExoPlayer doesn&#39;t need them (<a href="https://github.com/google/ExoPlayer/issues/10049">#10049</a>).</li> <li>Throw checked exception when parsing RTSP timing (<a href="https://github.com/google/ExoPlayer/issues/10165">#10165</a>).</li> <li>Add RTP reader for VP9 (<a href="https://github.com/androidx/media/pull/64">#47</a>).</li> <li>Add RTP reader for OPUS (<a href="https://github.com/androidx/media/pull/53">#53</a>).</li> </ul></li> <li>Data sources: <ul> <li>Rename <code translate="no" dir="ltr">DummyDataSource</code> to <code translate="no" dir="ltr">PlaceholderDataSource</code>.</li> <li>Workaround OkHttp interrupt handling.</li> </ul></li> <li>Session: <ul> <li>Replace <code translate="no" dir="ltr">MediaSession.MediaItemFiller</code> with <code translate="no" dir="ltr">MediaSession.Callback.onAddMediaItems</code> to allow asynchronous resolution of requests.</li> <li>Support <code translate="no" dir="ltr">setMediaItems(s)</code> methods when <code translate="no" dir="ltr">MediaController</code> connects to a legacy media session.</li> <li>Remove <code translate="no" dir="ltr">MediaController.setMediaUri</code> and <code translate="no" dir="ltr">MediaSession.Callback.onSetMediaUri</code>. The same functionality can be achieved by using <code translate="no" dir="ltr">MediaController.setMediaItem</code> and <code translate="no" dir="ltr">MediaSession.Callback.onAddMediaItems</code>.</li> <li>Forward legacy <code translate="no" dir="ltr">MediaController</code> calls to play media to <code translate="no" dir="ltr">MediaSession.Callback.onAddMediaItems</code> instead of <code translate="no" dir="ltr">onSetMediaUri</code>.</li> <li>Add <code translate="no" dir="ltr">MediaNotification.Provider</code> and <code translate="no" dir="ltr">DefaultMediaNotificationProvider</code> to provide customization of the notification.</li> <li>Add <code translate="no" dir="ltr">BitmapLoader</code> and <code translate="no" dir="ltr">SimpleBitmapLoader</code> for downloading artwork images.</li> <li>Add <code translate="no" dir="ltr">MediaSession.setCustomLayout()</code> to provide backwards compatibility with the legacy session.</li> <li>Add <code translate="no" dir="ltr">MediaSession.setSessionExtras()</code> to provide feature parity with legacy session.</li> <li>Rename <code translate="no" dir="ltr">MediaSession.MediaSessionCallback</code> to <code translate="no" dir="ltr">MediaSession.Callback</code>, <code translate="no" dir="ltr">MediaLibrarySession.MediaLibrarySessionCallback</code> to <code translate="no" dir="ltr">MediaLibrarySession.Callback</code> and <code translate="no" dir="ltr">MediaSession.Builder.setSessionCallback</code> to <code translate="no" dir="ltr">setCallback</code>.</li> <li>Fix NPE in <code translate="no" dir="ltr">MediaControllerImplLegacy</code> (<a href="https://github.com/androidx/media/pull/59">#59</a>).</li> <li>Update session position info on timeline change(<a href="https://github.com/androidx/media/issues/51">#51</a>).</li> <li>Fix NPE in <code translate="no" dir="ltr">MediaControllerImplBase</code> after releasing controller (<a href="https://github.com/androidx/media/issues/74">#74</a>).</li> </ul></li> <li>Ad playback / IMA: <ul> <li>Decrease ad polling rate from every 100ms to every 200ms, to line up with Media Rating Council (MRC) recommendations.</li> </ul></li> <li>FFmpeg extension: <ul> <li>Update CMake version to <code translate="no" dir="ltr">3.21.0+</code> to avoid a CMake bug causing AndroidStudio&#39;s gradle sync to fail (<a href="https://github.com/google/ExoPlayer/issues/9933">#9933</a>).</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">Player.Listener.onTracksChanged(TrackGroupArray, TrackSelectionArray)</code>. Use <code translate="no" dir="ltr">Player.Listener.onTracksChanged(Tracks)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">Player.getCurrentTrackGroups</code> and <code translate="no" dir="ltr">Player.getCurrentTrackSelections</code>. Use <code translate="no" dir="ltr">Player.getCurrentTracks</code> instead. You can also continue to use <code translate="no" dir="ltr">ExoPlayer.getCurrentTrackGroups</code> and <code translate="no" dir="ltr">ExoPlayer.getCurrentTrackSelections</code>, although these methods remain deprecated.</li> <li>Remove <code translate="no" dir="ltr">DownloadHelper</code> <code translate="no" dir="ltr">DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT</code> and <code translate="no" dir="ltr">DEFAULT_TRACK_SELECTOR_PARAMETERS</code> constants. Use <code translate="no" dir="ltr">getDefaultTrackSelectorParameters(Context)</code> instead when possible, and <code translate="no" dir="ltr">DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT</code> otherwise.</li> <li>Remove constructor <code translate="no" dir="ltr">DefaultTrackSelector(ExoTrackSelection.Factory)</code>. Use <code translate="no" dir="ltr">DefaultTrackSelector(Context, ExoTrackSelection.Factory)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">Transformer.Builder.setContext</code>. The <code translate="no" dir="ltr">Context</code> should be passed to the <code translate="no" dir="ltr">Transformer.Builder</code> constructor instead.</li> </ul></li> </ul> <h3 id="1.0.0-alpha03" data-text="Version 1.0.0-alpha03" tabindex="-1">Version 1.0.0-alpha03</h3> <p>March 14, 2022</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-alpha03</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-alpha03">Version 1.0.0-alpha03 contains these commits.</a></p> <p>This corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.17.1">ExoPlayer 2.17.1 release</a>.</p> <ul> <li>Audio: <ul> <li>Fix error checking audio capabilities for Dolby Atmos (E-AC3-JOC) in HLS.</li> </ul></li> <li>Extractors: <ul> <li>FMP4: Fix issue where emsg sample metadata could be output in the wrong order for streams containing both v0 and v1 emsg atoms (<a href="https://github.com/google/ExoPlayer/issues/9996">#9996</a>).</li> </ul></li> <li>Text: <ul> <li>Fix the interaction of <code translate="no" dir="ltr">SingleSampleMediaSource.Factory.setTrackId</code> and <code translate="no" dir="ltr">MediaItem.SubtitleConfiguration.Builder.setId</code> to prioritise the <code translate="no" dir="ltr">SubtitleConfiguration</code> field and fall back to the <code translate="no" dir="ltr">Factory</code> value if it&#39;s not set (<a href="https://github.com/google/ExoPlayer/issues/10016">#10016</a>).</li> </ul></li> <li>Ad playback: <ul> <li>Fix audio underruns between ad periods in live HLS SSAI streams.</li> </ul></li> </ul> <h3 id="1.0.0-alpha02" data-text="Version 1.0.0-alpha02" tabindex="-1">Version 1.0.0-alpha02</h3> <p>March 2, 2022</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-alpha02</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-alpha02">Version 1.0.0-alpha02 contains these commits.</a></p> <p>This corresponds to the <a href="https://github.com/google/ExoPlayer/releases/tag/r2.17.0">ExoPlayer 2.17.0 release</a>.</p> <ul> <li>Core Library: <ul> <li>Add protected method <code translate="no" dir="ltr">DefaultRenderersFactory.getCodecAdapterFactory()</code> so that subclasses of <code translate="no" dir="ltr">DefaultRenderersFactory</code> that override <code translate="no" dir="ltr">buildVideoRenderers()</code> or <code translate="no" dir="ltr">buildAudioRenderers()</code> can access the codec adapter factory and pass it to <code translate="no" dir="ltr">MediaCodecRenderer</code> instances they create.</li> <li>Propagate ICY header fields <code translate="no" dir="ltr">name</code> and <code translate="no" dir="ltr">genre</code> to <code translate="no" dir="ltr">MediaMetadata.station</code> and <code translate="no" dir="ltr">MediaMetadata.genre</code> respectively so that they reach the app via <code translate="no" dir="ltr">Player.Listener.onMediaMetadataChanged()</code> (<a href="https://github.com/google/ExoPlayer/issues/9677">#9677</a>).</li> <li>Remove null keys from <code translate="no" dir="ltr">DefaultHttpDataSource#getResponseHeaders</code>.</li> <li>Sleep and retry when creating a <code translate="no" dir="ltr">MediaCodec</code> instance fails. This works around an issue that occurs on some devices when switching a surface from a secure codec to another codec (<a href="https://github.com/google/ExoPlayer/issues/8696">#8696</a>).</li> <li>Add <code translate="no" dir="ltr">MediaCodecAdapter.getMetrics()</code> to allow users obtain metrics data from <code translate="no" dir="ltr">MediaCodec</code>. (<a href="https://github.com/google/ExoPlayer/issues/9766">#9766</a>).</li> <li>Fix Maven dependency resolution (<a href="https://github.com/google/ExoPlayer/issues/8353">#8353</a>).</li> <li>Disable automatic speed adjustment for live streams that neither have low-latency features nor a user request setting the speed (<a href="https://github.com/google/ExoPlayer/issues/9329">#9329</a>).</li> <li>Rename <code translate="no" dir="ltr">DecoderCounters#inputBufferCount</code> to <code translate="no" dir="ltr">queuedInputBufferCount</code>.</li> <li>Make <code translate="no" dir="ltr">SimpleExoPlayer.renderers</code> private. Renderers can be accessed via <code translate="no" dir="ltr">ExoPlayer.getRenderer</code>.</li> <li>Updated some <code translate="no" dir="ltr">AnalyticsListener.EventFlags</code> constant values to match values in <code translate="no" dir="ltr">Player.EventFlags</code>.</li> <li>Split <code translate="no" dir="ltr">AnalyticsCollector</code> into an interface and default implementation to allow it to be stripped by R8 if an app doesn&#39;t need it.</li> </ul></li> <li>Track selection: <ul> <li>Support preferred video role flags in track selection (<a href="https://github.com/google/ExoPlayer/issues/9402">#9402</a>).</li> <li>Update video track selection logic to take preferred MIME types and role flags into account when selecting multiple video tracks for adaptation (<a href="https://github.com/google/ExoPlayer/issues/9519">#9519</a>).</li> <li>Update video and audio track selection logic to only choose formats for adaptive selections that have the same level of decoder and hardware support (<a href="https://github.com/google/ExoPlayer/issues/9565">#9565</a>).</li> <li>Update video track selection logic to prefer more efficient codecs if multiple codecs are supported by primary, hardware-accelerated decoders (<a href="https://github.com/google/ExoPlayer/issues/4835">#4835</a>).</li> <li>Prefer audio content preferences (for example, the &quot;default&quot; audio track or a track matching the system locale language) over technical track selection constraints (for example, preferred MIME type, or maximum channel count).</li> <li>Fix track selection issue where overriding one track group did not disable other track groups of the same type (<a href="https://github.com/google/ExoPlayer/issues/9675">#9675</a>).</li> <li>Fix track selection issue where a mixture of non-empty and empty track overrides is not applied correctly (<a href="https://github.com/google/ExoPlayer/issues/9649">#9649</a>).</li> <li>Prohibit duplicate <code translate="no" dir="ltr">TrackGroup</code>s in a <code translate="no" dir="ltr">TrackGroupArray</code>. <code translate="no" dir="ltr">TrackGroup</code>s can always be made distinguishable by setting an <code translate="no" dir="ltr">id</code> in the <code translate="no" dir="ltr">TrackGroup</code> constructor. This fixes a crash when resuming playback after backgrounding the app with an active track override (<a href="https://github.com/google/ExoPlayer/issues/9718">#9718</a>).</li> <li>Amend logic in <code translate="no" dir="ltr">AdaptiveTrackSelection</code> to allow a quality increase under sufficient network bandwidth even if playback is very close to the live edge (<a href="https://github.com/google/ExoPlayer/issues/9784">#9784</a>).</li> </ul></li> <li>Video: <ul> <li>Fix decoder fallback logic for Dolby Vision to use a compatible H264/H265 decoder if needed.</li> </ul></li> <li>Audio: <ul> <li>Fix decoder fallback logic for Dolby Atmos (E-AC3-JOC) to use a compatible E-AC3 decoder if needed.</li> <li>Change <code translate="no" dir="ltr">AudioCapabilities</code> APIs to require passing explicitly <code translate="no" dir="ltr">AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES</code> instead of <code translate="no" dir="ltr">null</code>.</li> <li>Allow customization of the <code translate="no" dir="ltr">AudioTrack</code> buffer size calculation by injecting an <code translate="no" dir="ltr">AudioTrackBufferSizeProvider</code> to <code translate="no" dir="ltr">DefaultAudioSink</code>. (<a href="https://github.com/google/ExoPlayer/issues/8891">#8891</a>).</li> <li>Retry <code translate="no" dir="ltr">AudioTrack</code> creation if the requested buffer size was &gt; 1MB. (<a href="https://github.com/google/ExoPlayer/issues/9712">#9712</a>).</li> </ul></li> <li>Extractors: <ul> <li>WAV: Add support for RF64 streams (<a href="https://github.com/google/ExoPlayer/issues/9543">#9543</a>).</li> <li>Fix incorrect parsing of H.265 SPS NAL units (<a href="https://github.com/google/ExoPlayer/issues/9719">#9719</a>).</li> <li>Parse Vorbis Comments (including <code translate="no" dir="ltr">METADATA_BLOCK_PICTURE</code>) in Ogg Opus and Ogg Vorbis files.</li> </ul></li> <li>Text: <ul> <li>Add a <code translate="no" dir="ltr">MediaItem.SubtitleConfiguration.id</code> field which is propagated to the <code translate="no" dir="ltr">Format.id</code> field of the subtitle track created from the configuration (<a href="https://github.com/google/ExoPlayer/issues/9673">#9673</a>).</li> <li>Add basic support for WebVTT subtitles in Matroska containers (<a href="https://github.com/google/ExoPlayer/issues/9886">#9886</a>).</li> <li>Prevent <code translate="no" dir="ltr">Cea708Decoder</code> from reading more than the declared size of a service block.</li> </ul></li> <li>DRM: <ul> <li>Remove <code translate="no" dir="ltr">playbackLooper</code> from <code translate="no" dir="ltr">DrmSessionManager.(pre)acquireSession</code>. When a <code translate="no" dir="ltr">DrmSessionManager</code> is used by an app in a custom <code translate="no" dir="ltr">MediaSource</code>, the <code translate="no" dir="ltr">playbackLooper</code> needs to be passed to <code translate="no" dir="ltr">DrmSessionManager.setPlayer</code> instead.</li> </ul></li> <li>Ad playback / IMA: <ul> <li>Add support for <a href="https://support.google.com/admanager/answer/6147120">IMA Dynamic Ad Insertion (DAI)</a> (<a href="https://github.com/google/ExoPlayer/issues/8213">#8213</a>).</li> <li>Add a method to <code translate="no" dir="ltr">AdPlaybackState</code> to allow resetting an ad group so that it can be played again (<a href="https://github.com/google/ExoPlayer/issues/9615">#9615</a>).</li> <li>Enforce playback speed of 1.0 during ad playback (<a href="https://github.com/google/ExoPlayer/issues/9018">#9018</a>).</li> <li>Fix issue where an ad group that failed to load caused an immediate playback reset (<a href="https://github.com/google/ExoPlayer/issues/9929">#9929</a>).</li> </ul></li> <li>UI: <ul> <li>Fix the color of the numbers in <code translate="no" dir="ltr">StyledPlayerView</code> rewind and fastforward buttons when using certain themes (<a href="https://github.com/google/ExoPlayer/issues/9765">#9765</a>).</li> <li>Correctly translate playback speed strings (<a href="https://github.com/google/ExoPlayer/issues/9811">#9811</a>).</li> </ul></li> <li>DASH: <ul> <li>Add parsed essential and supplemental properties to the <code translate="no" dir="ltr">Representation</code> (<a href="https://github.com/google/ExoPlayer/issues/9579">#9579</a>).</li> <li>Support the <code translate="no" dir="ltr">forced-subtitle</code> track role (<a href="https://github.com/google/ExoPlayer/issues/9727">#9727</a>).</li> <li>Stop interpreting the <code translate="no" dir="ltr">main</code> track role as <code translate="no" dir="ltr">C.SELECTION_FLAG_DEFAULT</code>.</li> <li>Fix base URL exclusion logic for manifests that do not declare the DVB namespace (<a href="https://github.com/google/ExoPlayer/issues/9856">#9856</a>).</li> <li>Support relative <code translate="no" dir="ltr">MPD.Location</code> URLs (<a href="https://github.com/google/ExoPlayer/issues/9939">#9939</a>).</li> </ul></li> <li>HLS: <ul> <li>Correctly populate <code translate="no" dir="ltr">Format.label</code> for audio only HLS streams (<a href="https://github.com/google/ExoPlayer/issues/9608">#9608</a>).</li> <li>Use chunkless preparation by default to improve start up time. If your renditions contain muxed closed-caption tracks that are <strong>not</strong> declared in the master playlist, you should add them to the master playlist to be available for playback, or turn off chunkless preparation with <code translate="no" dir="ltr">HlsMediaSource.Factory.setAllowChunklessPreparation(false)</code>.</li> <li>Support key-frame accurate seeking in HLS (<a href="https://github.com/google/ExoPlayer/issues/2882">#2882</a>).</li> </ul></li> <li>RTSP: <ul> <li>Provide a client API to override the <code translate="no" dir="ltr">SocketFactory</code> used for any server connection (<a href="https://github.com/google/ExoPlayer/pull/9606">#9606</a>).</li> <li>Prefer DIGEST authentication method over BASIC if both are present (<a href="https://github.com/google/ExoPlayer/issues/9800">#9800</a>).</li> <li>Handle when RTSP track timing is not available (<a href="https://github.com/google/ExoPlayer/issues/9775">#9775</a>).</li> <li>Ignore invalid RTP-Info header values (<a href="https://github.com/google/ExoPlayer/issues/9619">#9619</a>).</li> </ul></li> <li>Transformer: <ul> <li>Increase required min API version to 21.</li> <li><code translate="no" dir="ltr">TransformationException</code> is now used to describe errors that occur during a transformation.</li> <li>Add <code translate="no" dir="ltr">TransformationRequest</code> for specifying the transformation options.</li> <li>Allow multiple listeners to be registered.</li> <li>Fix Transformer being stuck when the codec output is partially read.</li> <li>Fix potential NPE in <code translate="no" dir="ltr">Transformer.getProgress</code> when releasing the muxer throws.</li> <li>Add a demo app for applying transformations.</li> </ul></li> <li>MediaSession extension: <ul> <li>By default, <code translate="no" dir="ltr">MediaSessionConnector</code> now clears the playlist on stop. Apps that want the playlist to be retained can call <code translate="no" dir="ltr">setClearMediaItemsOnStop(false)</code> on the connector.</li> </ul></li> <li>Cast extension: <ul> <li>Fix bug that prevented <code translate="no" dir="ltr">CastPlayer</code> from calling <code translate="no" dir="ltr">onIsPlayingChanged</code> correctly (<a href="https://github.com/google/ExoPlayer/issues/9792">#9792</a>).</li> <li>Support audio metadata including artwork with <code translate="no" dir="ltr">DefaultMediaItemConverter</code> (<a href="https://github.com/google/ExoPlayer/issues/9663">#9663</a>).</li> </ul></li> <li>FFmpeg extension: <ul> <li>Make <code translate="no" dir="ltr">build_ffmpeg.sh</code> depend on LLVM&#39;s bin utils instead of GNU&#39;s (<a href="https://github.com/google/ExoPlayer/issues/9933">#9933</a>).</li> </ul></li> <li>Android 12 compatibility: <ul> <li>Upgrade the Cast extension to depend on <code translate="no" dir="ltr">com.google.android.gms:play-services-cast-framework:20.1.0</code>. Earlier versions of <code translate="no" dir="ltr">play-services-cast-framework</code> are not compatible with apps targeting Android 12, and will crash with an <code translate="no" dir="ltr">IllegalArgumentException</code> when creating <code translate="no" dir="ltr">PendingIntent</code>s (<a href="https://github.com/google/ExoPlayer/issues/9528">#9528</a>).</li> </ul></li> <li>Remove deprecated symbols: <ul> <li>Remove <code translate="no" dir="ltr">Player.EventListener</code>. Use <code translate="no" dir="ltr">Player.Listener</code> instead.</li> <li>Remove <code translate="no" dir="ltr">MediaSourceFactory#setDrmSessionManager</code>, <code translate="no" dir="ltr">MediaSourceFactory#setDrmHttpDataSourceFactory</code>, and <code translate="no" dir="ltr">MediaSourceFactory#setDrmUserAgent</code>. Use <code translate="no" dir="ltr">MediaSourceFactory#setDrmSessionManagerProvider</code> instead.</li> <li>Remove <code translate="no" dir="ltr">MediaSourceFactory#setStreamKeys</code>. Use <code translate="no" dir="ltr">MediaItem.Builder#setStreamKeys</code> instead.</li> <li>Remove <code translate="no" dir="ltr">MediaSourceFactory#createMediaSource(Uri)</code>. Use <code translate="no" dir="ltr">MediaSourceFactory#createMediaSource(MediaItem)</code> instead.</li> <li>Remove <code translate="no" dir="ltr">setTag</code> from <code translate="no" dir="ltr">DashMediaSource</code>, <code translate="no" dir="ltr">HlsMediaSource</code> and <code translate="no" dir="ltr">SsMediaSource</code>. Use <code translate="no" dir="ltr">MediaItem.Builder#setTag</code> instead.</li> <li>Remove <code translate="no" dir="ltr">DashMediaSource#setLivePresentationDelayMs(long, boolean)</code>. Use <code translate="no" dir="ltr">MediaItem.Builder#setLiveConfiguration</code> and <code translate="no" dir="ltr">MediaItem.LiveConfiguration.Builder#setTargetOffsetMs</code> to override the manifest, or <code translate="no" dir="ltr">DashMediaSource#setFallbackTargetLiveOffsetMs</code> to provide a fallback value.</li> <li>Remove <code translate="no" dir="ltr">(Simple)ExoPlayer.setThrowsWhenUsingWrongThread</code>. Opting out of the thread enforcement is no longer possible.</li> <li>Remove <code translate="no" dir="ltr">ActionFile</code> and <code translate="no" dir="ltr">ActionFileUpgradeUtil</code>. Use ExoPlayer 2.16.1 or before to use <code translate="no" dir="ltr">ActionFileUpgradeUtil</code> to merge legacy action files into <code translate="no" dir="ltr">DefaultDownloadIndex</code>.</li> <li>Remove <code translate="no" dir="ltr">ProgressiveMediaSource#setExtractorsFactory</code>. Use <code translate="no" dir="ltr">ProgressiveMediaSource.Factory(DataSource.Factory, ExtractorsFactory)</code> constructor instead.</li> <li>Remove <code translate="no" dir="ltr">ProgressiveMediaSource.Factory#setTag</code> and, and <code translate="no" dir="ltr">ProgressiveMediaSource.Factory#setCustomCacheKey</code>. Use <code translate="no" dir="ltr">MediaItem.Builder#setTag</code> and <code translate="no" dir="ltr">MediaItem.Builder#setCustomCacheKey</code> instead.</li> <li>Remove <code translate="no" dir="ltr">DefaultRenderersFactory(Context, @ExtensionRendererMode int)</code> and <code translate="no" dir="ltr">DefaultRenderersFactory(Context, @ExtensionRendererMode int, long)</code> constructors. Use the <code translate="no" dir="ltr">DefaultRenderersFactory(Context)</code> constructor, <code translate="no" dir="ltr">DefaultRenderersFactory#setExtensionRendererMode</code>, and <code translate="no" dir="ltr">DefaultRenderersFactory#setAllowedVideoJoiningTimeMs</code> instead.</li> <li>Remove all public <code translate="no" dir="ltr">CronetDataSource</code> constructors. Use <code translate="no" dir="ltr">CronetDataSource.Factory</code> instead.</li> </ul></li> <li>Change the following <code translate="no" dir="ltr">IntDefs</code> to <code translate="no" dir="ltr">@Target(TYPE_USE)</code> only. This may break the compilation of usages in Kotlin, which can be fixed by moving the annotation to annotate the type (<code translate="no" dir="ltr">Int</code>). <ul> <li><code translate="no" dir="ltr">@AacAudioObjectType</code></li> <li><code translate="no" dir="ltr">@Ac3Util.SyncFrameInfo.StreamType</code></li> <li><code translate="no" dir="ltr">@AdLoadException.Type</code></li> <li><code translate="no" dir="ltr">@AdtsExtractor.Flags</code></li> <li><code translate="no" dir="ltr">@AmrExtractor.Flags</code></li> <li><code translate="no" dir="ltr">@AspectRatioFrameLayout.ResizeMode</code></li> <li><code translate="no" dir="ltr">@AudioFocusManager.PlayerCommand</code></li> <li><code translate="no" dir="ltr">@AudioSink.SinkFormatSupport</code></li> <li><code translate="no" dir="ltr">@BinarySearchSeeker.TimestampSearchResult.Type</code></li> <li><code translate="no" dir="ltr">@BufferReplacementMode</code></li> <li><code translate="no" dir="ltr">@C.BufferFlags</code></li> <li><code translate="no" dir="ltr">@C.ColorRange</code></li> <li><code translate="no" dir="ltr">@C.ColorSpace</code></li> <li><code translate="no" dir="ltr">@C.ColorTransfer</code></li> <li><code translate="no" dir="ltr">@C.CryptoMode</code></li> <li><code translate="no" dir="ltr">@C.Encoding</code></li> <li><code translate="no" dir="ltr">@C.PcmEncoding</code></li> <li><code translate="no" dir="ltr">@C.Projection</code></li> <li><code translate="no" dir="ltr">@C.SelectionReason</code></li> <li><code translate="no" dir="ltr">@C.StereoMode</code></li> <li><code translate="no" dir="ltr">@C.VideoOutputMode</code></li> <li><code translate="no" dir="ltr">@CacheDataSource.Flags</code></li> <li><code translate="no" dir="ltr">@CaptionStyleCompat.EdgeType</code></li> <li><code translate="no" dir="ltr">@DataSpec.Flags</code></li> <li><code translate="no" dir="ltr">@DataSpec.HttpMethods</code></li> <li><code translate="no" dir="ltr">@DecoderDiscardReasons</code></li> <li><code translate="no" dir="ltr">@DecoderReuseResult</code></li> <li><code translate="no" dir="ltr">@DefaultAudioSink.OutputMode</code></li> <li><code translate="no" dir="ltr">@DefaultDrmSessionManager.Mode</code></li> <li><code translate="no" dir="ltr">@DefaultTrackSelector.SelectionEligibility</code></li> <li><code translate="no" dir="ltr">@DefaultTsPayloadReaderFactory.Flags</code></li> <li><code translate="no" dir="ltr">@EGLSurfaceTexture.SecureMode</code></li> <li><code translate="no" dir="ltr">@EbmlProcessor.ElementType</code></li> <li><code translate="no" dir="ltr">@ExoMediaDrm.KeyRequest.RequestType</code></li> <li><code translate="no" dir="ltr">@ExtensionRendererMode</code></li> <li><code translate="no" dir="ltr">@Extractor.ReadResult</code></li> <li><code translate="no" dir="ltr">@FileTypes.Type</code></li> <li><code translate="no" dir="ltr">@FlacExtractor.Flags</code> (in <code translate="no" dir="ltr">com.google.android.exoplayer2.ext.flac</code> package)</li> <li><code translate="no" dir="ltr">@FlacExtractor.Flags</code> (in <code translate="no" dir="ltr">com.google.android.exoplayer2.extractor.flac</code> package)</li> <li><code translate="no" dir="ltr">@FragmentedMp4Extractor.Flags</code></li> <li><code translate="no" dir="ltr">@HlsMediaPlaylist.PlaylistType</code></li> <li><code translate="no" dir="ltr">@HttpDataSourceException.Type</code></li> <li><code translate="no" dir="ltr">@IllegalClippingException.Reason</code></li> <li><code translate="no" dir="ltr">@IllegalMergeException.Reason</code></li> <li><code translate="no" dir="ltr">@LoadErrorHandlingPolicy.FallbackType</code></li> <li><code translate="no" dir="ltr">@MatroskaExtractor.Flags</code></li> <li><code translate="no" dir="ltr">@Mp3Extractor.Flags</code></li> <li><code translate="no" dir="ltr">@Mp4Extractor.Flags</code></li> <li><code translate="no" dir="ltr">@NotificationUtil.Importance</code></li> <li><code translate="no" dir="ltr">@PlaybackException.FieldNumber</code></li> <li><code translate="no" dir="ltr">@PlayerNotificationManager.Priority</code></li> <li><code translate="no" dir="ltr">@PlayerNotificationManager.Visibility</code></li> <li><code translate="no" dir="ltr">@PlayerView.ShowBuffering</code></li> <li><code translate="no" dir="ltr">@Renderer.State</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.AdaptiveSupport</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.Capabilities</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.DecoderSupport</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.FormatSupport</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.HardwareAccelerationSupport</code></li> <li><code translate="no" dir="ltr">@RendererCapabilities.TunnelingSupport</code></li> <li><code translate="no" dir="ltr">@SampleStream.ReadDataResult</code></li> <li><code translate="no" dir="ltr">@SampleStream.ReadFlags</code></li> <li><code translate="no" dir="ltr">@StyledPlayerView.ShowBuffering</code></li> <li><code translate="no" dir="ltr">@SubtitleView.ViewType</code></li> <li><code translate="no" dir="ltr">@TextAnnotation.Position</code></li> <li><code translate="no" dir="ltr">@TextEmphasisSpan.MarkFill</code></li> <li><code translate="no" dir="ltr">@TextEmphasisSpan.MarkShape</code></li> <li><code translate="no" dir="ltr">@Track.Transformation</code></li> <li><code translate="no" dir="ltr">@TrackOutput.SampleDataPart</code></li> <li><code translate="no" dir="ltr">@Transformer.ProgressState</code></li> <li><code translate="no" dir="ltr">@TsExtractor.Mode</code></li> <li><code translate="no" dir="ltr">@TsPayloadReader.Flags</code></li> <li><code translate="no" dir="ltr">@WebvttCssStyle.FontSizeUnit</code></li> </ul></li> </ul> <h3 id="1.0.0-alpha01" data-text="Version 1.0.0-alpha01" tabindex="-1">Version 1.0.0-alpha01</h3> <p>October 27, 2021</p> <p><code translate="no" dir="ltr">androidx.media3:media3-*:1.0.0-alpha01</code> is released. <a href="https://github.com/androidx/media/commits/1.0.0-alpha01">Version 1.0.0-alpha01 contains these commits.</a></p> <h4 id="new_features_2" data-text="New features" tabindex="-1">New features</h4> <p>Media3 is the new home for media support libraries, including ExoPlayer. The first alpha contains early, functional implementations of libraries for implementing media use cases, including:</p> <ul> <li>ExoPlayer, an application-level media player for Android that is easy to customize and extend.</li> <li>Media session functionality, for exposing and controlling playbacks. This new session module uses the same <code translate="no" dir="ltr">Player</code> interface as ExoPlayer.</li> <li>UI components for building media playback user interfaces.</li> <li>Modules wrapping functionality in other libraries for use with ExoPlayer, for example, ad insertion via the IMA SDK.</li> </ul> <p>For more information, see the <a href="https://github.com/androidx/media">Media3 GitHub project</a>.</p> <p>ExoPlayer was previously hosted in a separate <a href="https://github.com/google/ExoPlayer">ExoPlayer GitHub project</a>. In Media3 its package name is <code translate="no" dir="ltr">androidx.media3.exoplayer</code>. We plan to continue to maintain and release the ExoPlayer GitHub project for a while to give apps time to migrate to Media3. Media3 has replacements for all the ExoPlayer modules, except for the legacy media2 and mediasession extensions, which are replaced by the new <code translate="no" dir="ltr">media3-session</code> module. This provides direct integration between players and media sessions without needing to use an adapter/connector class.</p> <devsite-hats-survey class="nocontent" hats-id="VxqvKSur40kxBYCLVTd0SSGykbno" listnr-id="5207477"></devsite-hats-survey> </div> <devsite-recommendations display="in-page" hidden yield> </devsite-recommendations> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <devsite-recommendations id="recommendations-link" yield></devsite-recommendations> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Content and code samples on this page are subject to the licenses described in the <a href="/license">Content License</a>. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.</p> <p>Last updated 2024-11-19 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2024-11-19 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> <nav class="devsite-footer-promos nocontent" aria-label="Promotions"> <ul class="devsite-footer-promos-list"> <li class="devsite-footer-promo"> <a href="//x.com/AndroidDev" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer X Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-x_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="X"> <img class="devsite-footer-promo-icon" src="/_static/android/images/logo-x.svg" loading="lazy" alt="X"> </picture> <span class="devsite-footer-promo-label"> X </span> </a> <div class="devsite-footer-promo-description">Follow @AndroidDev on X</div> </li> <li class="devsite-footer-promo"> <a href="//www.youtube.com/user/androiddevelopers" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer YouTube Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-youtube_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="YouTube"> <img class="devsite-footer-promo-icon" src="//www.gstatic.com/images/icons/material/product/2x/youtube_48dp.png" loading="lazy" alt="YouTube"> </picture> <span class="devsite-footer-promo-label"> YouTube </span> </a> <div class="devsite-footer-promo-description">Check out Android Developers on YouTube</div> </li> <li class="devsite-footer-promo"> <a href="//www.linkedin.com/showcase/androiddev" class="devsite-footer-promo-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer LinkedIn Promo" > <picture> <source class="devsite-dark-theme" srcset="https://developer.android.com/_static/android/images/logo-linkedin_dt.svg" media="(prefers-color-scheme: dark)" loading="lazy" alt="LinkedIn"> <img class="devsite-footer-promo-icon" src="/_static/android/images/logo-linkedin.svg" loading="lazy" alt="LinkedIn"> </picture> <span class="devsite-footer-promo-label"> LinkedIn </span> </a> <div class="devsite-footer-promo-description">Connect with the Android Developers community on LinkedIn</div> </li> </ul> </nav> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">More Android</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com/enterprise/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Android for Enterprise </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.android.com/security-center/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Security </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//source.android.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Source </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/news" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > News </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//android-developers.googleblog.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > Blog </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/podcasts" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" > Podcasts </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Discover</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/games" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Gaming </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/ml" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Machine Learning </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/health-and-fitness" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Health & Fitness </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/media" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Camera & Media </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/privacy" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Privacy </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/training/connectivity/5g" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > 5G </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Android Devices</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/large-screens" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Large screens </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/wear" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Wear OS </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/chrome-os" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > ChromeOS devices </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/cars" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Android for cars </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/tv" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android TV </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Releases</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/15" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android 15 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/14" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Android 14 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/13" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Android 13 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/12" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Android 12 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/11" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android 11 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/10" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > Android 10 </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/versions/pie" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" > Pie </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Documentation and Downloads</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/studio/intro" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Android Studio guide </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/guide" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Developers guides </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/reference" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > API reference </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/studio" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Download Studio </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/ndk" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Android NDK </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Support</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//issuetracker.google.com/issues/new?component=190923&amp;template=841312" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Report platform bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//issuetracker.google.com/issues/new?component=192697" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Report documentation bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//support.google.com/googleplay/android-developer" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Google Play support </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://g.co/userresearch/androiddeveloperfooter" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Join research studies </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-sites" aria-label="Other Google Developers websites"> <a href="https://developers.google.com/" class="devsite-footer-sites-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Developers Link"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-google-for-developers-dark-theme.svg" media="(prefers-color-scheme: none)" class="devsite-dark-theme" loading="lazy" alt="Google Developers"> <img class="devsite-footer-sites-logo" src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup-google-for-developers.svg" loading="lazy" alt="Google Developers"> </picture> </a> <ul class="devsite-footer-sites-list"> <li class="devsite-footer-sites-item"> <a href="//developer.android.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Android Link" > Android </a> </li> <li class="devsite-footer-sites-item"> <a href="//developer.chrome.com/home" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Chrome Link" > Chrome </a> </li> <li class="devsite-footer-sites-item"> <a href="//firebase.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Firebase Link" > Firebase </a> </li> <li class="devsite-footer-sites-item"> <a href="//cloud.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Cloud Platform Link" > Google Cloud Platform </a> </li> <li class="devsite-footer-sites-item"> <a href="//developers.google.com/products/" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer All products Link" > All products </a> </li> </ul> </nav> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/license" data-category="Site-Wide Custom Events" data-label="Footer License link" > License </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/distribute/marketing-tools/brand-guidelines" data-category="Site-Wide Custom Events" data-label="Footer Brand guidelines link" > Brand guidelines </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> <li class="devsite-footer-utility-item devsite-footer-utility-button"> <span class="devsite-footer-utility-description">Get news and tips by email</span> <a class="devsite-footer-utility-link gc-analytics-event" href="/updates" data-category="Site-Wide Custom Events" data-label="Footer Subscribe link" > Subscribe </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{&#34;at&#34;: &#34;True&#34;, &#34;ga4&#34;: [{&#34;id&#34;: &#34;G-QFRN08RN6E&#34;, &#34;purpose&#34;: 0}], &#34;ga4p&#34;: [{&#34;id&#34;: &#34;G-QFRN08RN6E&#34;, &#34;purpose&#34;: 0}], &#34;gtm&#34;: [{&#34;id&#34;: &#34;GTM-KMSWPCJ&#34;, &#34;purpose&#34;: 0}], &#34;parameters&#34;: {&#34;internalUser&#34;: &#34;False&#34;, &#34;language&#34;: {&#34;machineTranslated&#34;: &#34;False&#34;, &#34;requested&#34;: &#34;en&#34;, &#34;served&#34;: &#34;en&#34;}, &#34;pageType&#34;: &#34;article&#34;, &#34;projectName&#34;: &#34;Jetpack&#34;, &#34;signedIn&#34;: &#34;False&#34;, &#34;tenant&#34;: &#34;android&#34;, &#34;recommendations&#34;: {&#34;sourcePage&#34;: &#34;&#34;, &#34;sourceType&#34;: 0, &#34;sourceRank&#34;: 0, &#34;sourceIdenticalDescriptions&#34;: 0, &#34;sourceTitleWords&#34;: 0, &#34;sourceDescriptionWords&#34;: 0, &#34;experiment&#34;: &#34;&#34;}, &#34;experiment&#34;: {&#34;ids&#34;: &#34;&#34;}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <android-fully-clickable target=" .android-case-study .devsite-landing-row-item, .android-grouped-resources .devsite-landing-row-item, .android-grouped-resources-primary .devsite-landing-row-item, .android-grouped-resources-secondary .devsite-landing-row-item, .android-guide-cards .devsite-landing-row-item, .android-illustrated-resources-index .devsite-landing-row-item, .android-illustrated-resources-primary .devsite-landing-row-item, .android-illustrated-resources-secondary .devsite-landing-row-item, .android-illustrated-resources-secondary-small .devsite-landing-row-item, .android-illustrated-resources-tertiary .devsite-landing-row-item, .android-illustrated-resources-tertiary-small .devsite-landing-row-item, .android-promo .devsite-landing-row-item, .android-quick-link, .android-samples .devsite-card-wrapper, .fully-clickable" watch=".android-samples, devsite-content"></android-fully-clickable> <script nonce="famfi+4fKLjmAK+08fSzOl4kFfTLfO"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/js/app_loader.js', '[3,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android","https://android-dot-devsite-v2-prod.appspot.com",null,null,["/_pwa/android/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/favicon.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/android/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500,600,700|Google+Sans+Text:400,400italic,500,500italic,600,600italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyAP-jjEJBzmIyKR4F-3XITp8yM9T1gEEI8","AIzaSyB6xiKGDR5O3Ak2okS4rLkauxGUG7XP0hg","developer.android.com","AIzaSyAQk0fBONSGUqCNznf6Krs82Ap1-NV6J4o","AIzaSyCCxcqdrZ_7QMeLCRY20bh_SXdAYqy70KY",null,null,null,["Cloud__enable_free_trial_server_call","Profiles__enable_developer_profiles_callout","CloudShell__cloud_shell_button","MiscFeatureFlags__enable_firebase_utm","Cloud__enable_cloudx_ping","Search__enable_ai_eligibility_checks","Search__enable_page_map","Cloud__enable_cloud_dlp_service","DevPro__enable_cloud_innovators_plus","Profiles__enable_recognition_badges","Significatio__enable_by_tenant","MiscFeatureFlags__enable_explain_this_code","Cloud__enable_cloudx_experiment_ids","MiscFeatureFlags__enable_project_variables","Profiles__enable_complete_playlist_endpoint","Cloud__enable_legacy_calculator_redirect","MiscFeatureFlags__enable_variable_operator","Analytics__enable_clearcut_logging","MiscFeatureFlags__developers_footer_image","TpcFeatures__enable_required_headers","MiscFeatureFlags__enable_view_transitions","MiscFeatureFlags__developers_footer_dark_image","TpcFeatures__enable_mirror_tenant_redirects","Cloud__enable_cloud_facet_chat","Search__enable_dynamic_content_confidential_banner","Profiles__enable_public_developer_profiles","Profiles__require_profile_eligibility_for_signin","MiscFeatureFlags__emergency_css","Cloud__enable_cloud_shell_fte_user_flow","Profiles__enable_page_saving","Cloud__enable_llm_concierge_chat","MiscFeatureFlags__enable_dark_theme","Search__enable_ai_search_summaries","CloudShell__cloud_code_overflow_menu","Profiles__enable_dashboard_curated_recommendations","BookNav__enable_tenant_cache_key","Profiles__enable_completecodelab_endpoint","DevPro__enable_developer_subscriptions","Search__enable_suggestions_from_borg","Profiles__enable_release_notes_notifications","Experiments__reqs_query_experiments","Profiles__enable_awarding_url","Concierge__enable_pushui","EngEduTelemetry__enable_engedu_telemetry","Cloud__enable_cloud_shell","Profiles__enable_profile_collections"],null,null,"AIzaSyBLEMok-5suZ67qRPzx0qUtbnLmyT_kCVE","https://developerscontentserving-pa.googleapis.com","AIzaSyCM4QpTRSqP5qI4Dvjt4OAScIN8sOUlO-k","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[3,"android","Android Developers","developer.android.com",null,"android-dot-devsite-v2-prod.appspot.com",null,null,[null,1,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],[1,null,null,[1,20],"/recommendations"],null,null,null,[1,null,1],[1,1,null,1,1]],null,[18,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,null,null,null,null,null,null,null,null,null,null,1,null,null,null,"/images/lockup-dark-theme.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1,14,15,20,22,23,28,29,37,43],null,[[null,null,1],[1,1]],[[null,null,null,null,null,null,null,[["G-QFRN08RN6E"],null,null,[["G-QFRN08RN6E",1]]],null,null,null,null,1],null,[[1,1],[2,2]]],null,4,null,null,null,null,null,null,null,null,null,null,null,null,null,"android.devsite.google"],null,"pk_live_5170syrHvgGVmSx9sBrnWtA5luvk9BwnVcvIi7HizpwauFG96WedXsuXh790rtij9AmGllqPtMLfhe2RSwD6Pn38V00uBCydV4m"]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10