Jetpack Media3 define una interfaz Player
que describe la funcionalidad básica
para reproducir archivos de audio y video. ExoPlayer
es la implementación predeterminada
de esta interfaz en Media3. Recomendamos usar ExoPlayer, ya que proporciona un
un conjunto completo de funciones que abarcan la mayoría de los casos de uso de reproducción y está
se pueden personalizar para manejar cualquier caso de uso adicional que puedas tener. ExoPlayer también
abstrae la fragmentación del dispositivo y el SO para que el código funcione de manera coherente
en todo el ecosistema de Android. ExoPlayer incluye lo siguiente:
- Compatibilidad con playlists
- Compatibilidad con una variedad de transmisiones progresivas y adaptables formatos
- Compatibilidad con la inserción de anuncios del cliente y del servidor
- Compatibilidad con la reproducción protegida por DRM
En esta página, se explican algunos de los pasos clave para crear una reproducción y, para obtener más detalles, consulta nuestras guías completas sobre Media3 ExoPlayer.
Cómo comenzar
Para comenzar, agrega una dependencia en ExoPlayer, la IU y los módulos comunes de Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.4.0" implementation "androidx.media3:media3-ui:1.4.0" implementation "androidx.media3:media3-common:1.4.0"
Según tu caso de uso, es posible que necesites módulos adicionales de Media3,
como exoplayer-dash
, para reproducir transmisiones en el formato DASH.
Asegúrate de reemplazar 1.4.0
por tu versión preferida del elemento
biblioteca. Puedes consultar las notas de la versión.
para ver la versión más reciente.
Cómo crear un reproductor multimedia
Con Media3, puedes usar la implementación incluida de Player
de Google Cloud, ExoPlayer
, o puedes crear tu propia implementación personalizada.
Crea un ExoPlayer
La forma más sencilla de crear una instancia de ExoPlayer
es la siguiente:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
Puedes crear tu reproductor multimedia en el método de ciclo de vida onCreate()
de la
Activity
, Fragment
o Service
, donde se encuentra.
La Builder
incluye
varias opciones de personalización que podrían interesarte, como las siguientes:
setAudioAttributes()
para configurar el manejo del foco de audiosetHandleAudioBecomingNoisy()
para configurar el comportamiento de reproducción cuando se desconecta un dispositivo de salida de audiosetTrackSelector()
para configurar la selección de pistas
Media3 proporciona un componente de IU PlayerView
que puedes incluir en la biblioteca
archivo de diseño. Este componente encapsula un PlayerControlView
para la reproducción
controles, SubtitleView
para mostrar los subtítulos y Surface
para la renderización
video.
Cómo preparar el reproductor
Agrega elementos multimedia a una playlist para
la reproducción con métodos como
setMediaItem()
y addMediaItem()
.
Luego, llama a prepare()
para
comenzar a cargar medios y adquirir los recursos necesarios.
No debes realizar estos pasos antes de que la app esté en primer plano. Si el
el jugador está en un Activity
o Fragment
, esto significa prepararlo en la
Método de ciclo de vida de onStart()
en el nivel de API 24 y versiones posteriores, o bien onResume()
de ciclo de vida en el nivel de API 23 y versiones anteriores. En el caso de un jugador que está en un Service
,
puedes prepararlo en onCreate()
.
Cómo controlar el reproductor
Después de que el reproductor esté preparado, puedes controlar la reproducción llamando a métodos en el reproductor, por ejemplo:
play()
ypause()
para iniciar y pausar la reproducciónseekTo()
para buscar lo siguiente: una posición dentro del elemento multimedia actualseekToNextMediaItem()
yseekToPreviousMediaItem()
para navegar por la playlist
Se actualizarán los componentes de IU, como PlayerView
o PlayerControlView
.
de manera acorde cuando se vincula a un jugador.
Cómo liberar el reproductor
La reproducción puede requerir recursos limitados, como los videos
decodificadores, por lo que es importante llamar a release()
en el reproductor para liberar recursos cuando ya no lo necesites.
Si el reproductor está en un Activity
o Fragment
, suéltalo en la
Método de ciclo de vida de onStop()
en el nivel de API 24 y versiones posteriores, o bien onPause()
a partir del nivel de API 23. En el caso de un jugador que se encuentra en un Service
, puedes
lanzarlo en onDestroy()
.
Cómo administrar la reproducción con una sesión multimedia
En Android, las sesiones multimedia proporcionan una forma estandarizada de interactuar con un contenido multimedia. y el reproductor más allá de los límites del proceso. Cómo conectar una sesión multimedia con tu reproductor te permite anunciar la reproducción de tu contenido multimedia externamente y recibir reproducciones comandos de fuentes externas, por ejemplo, para integrarse con controles multimedia del sistema en dispositivos móviles y grandes dispositivos de pantalla.
Para usar sesiones multimedia, agrega una dependencia en el módulo Media3 Session:
implementation "androidx.media3:media3-session:1.4.0"
Cómo crear una sesión multimedia
Puedes crear un MediaSession
después de inicializar un jugador de la siguiente manera:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 sincroniza automáticamente el estado de Player
con el estado de
MediaSession
Esto funciona con cualquier implementación de Player
, incluidas
ExoPlayer
, CastPlayer
o una
o la implementación personalizada.
Otórgales control a otros clientes
Las apps cliente pueden implementar un controlador multimedia
para controlar la reproducción de tu sesión multimedia. Para recibir estas solicitudes, establece una
devolución de llamada cuando
creando tu MediaSession
.
Cuando un controlador esté a punto de conectarse a tu sesión multimedia, el
onConnect()
método. Puedes usar el ControllerInfo
proporcionado
para decidir si aceptar
o rechazar
la solicitud. Consulta un ejemplo de esto en la app de demostración de Media3 Session.
Una vez conectado, un control puede enviar comandos de reproducción a la sesión. El
y, luego, delega esos comandos al reproductor. Reproducción y playlist
los comandos definidos en la interfaz de Player
se controlan automáticamente
sesión.
Otros métodos de devolución de llamada permiten controlar, por ejemplo, las solicitudes de
comandos de reproducción personalizados
y modifica la playlist. De manera similar, estas devoluciones de llamada incluyen un objeto ControllerInfo
para que
puede determinar el control de acceso solicitud por solicitud.
Reproducción de contenido multimedia en segundo plano
Para seguir reproduciendo contenido multimedia cuando la app no está en primer plano, por ejemplo
para reproducir música, audiolibros o podcasts incluso cuando el usuario no tiene tu app
abierto, tu Player
y tu MediaSession
deben estar encapsulados en un
servicio en primer plano. Media3 proporciona la
MediaSessionService
para este fin.
Cómo implementar un MediaSessionService
Crea una clase que extienda MediaSessionService
y crea una instancia de tu
MediaSession
en el método del ciclo de vida de onCreate()
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
En el manifiesto, la clase Service
con un intent MediaSessionService
filtra y solicita el permiso FOREGROUND_SERVICE
para ejecutar un
servicio:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Por último, en la clase que creaste, anula el método onGetSession()
para controlar
el acceso de cliente a tu sesión multimedia. Muestra un MediaSession
para aceptar el
solicitud de conexión o mostrar null
para rechazar la solicitud.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Conéctate a tu IU
Ahora que tu sesión multimedia está en un Service
independiente de Activity
o
Fragment
donde se encuentra la IU del reproductor, puedes usar un MediaController
para vincular
entre ellas. En el método onStart()
de Activity
o Fragment
con tu
IU, crea un SessionToken
para tu MediaSession
y, luego, usa el SessionToken
para compilar un MediaController
. Se crea un MediaController
de forma asíncrona.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController
implementa la interfaz Player
, por lo que puedes usar la misma
con métodos como play()
y pause()
, para controlar la reproducción. Similar a otro
de configuración, recuerda liberar el objeto MediaController
cuando ya no esté
necesario, como el método de ciclo de vida de onStop()
de un Activity
, llamando
MediaController.releaseFuture()
Publica una notificación
Los servicios en primer plano deben publicar una notificación mientras están activos. R
MediaSessionService
creará automáticamente un
Notificación de MediaStyle
para
en la forma de un MediaNotification
.
Para proporcionar una notificación personalizada, crea una
MediaNotification.Provider
con DefaultMediaNotificationProvider.Builder
o creando una implementación personalizada de la interfaz del proveedor. Agrega tu
proveedor a tu MediaSession
con
setMediaNotificationProvider
Cómo anunciar tu biblioteca de contenido
Un MediaLibraryService
se basa en un MediaSessionService
permitiendo que el cliente
apps para explorar el contenido multimedia proporcionado por tu app. Las apps cliente implementan un
MediaBrowser
para interactuar
con tu MediaLibraryService
.
La implementación de un MediaLibraryService
es similar a la de un
MediaSessionService
, excepto que, en onGetSession()
, debes mostrar un
MediaLibrarySession
en lugar de MediaSession
. Comparado con un
MediaSession.Callback
, el MediaLibrarySession.Callback
incluye
que permiten al cliente del navegador navegar por el contenido que ofrece tu
servicio de biblioteca.
Al igual que con MediaSessionService
, declara el MediaLibraryService
en tu
manifiesto y solicita el permiso FOREGROUND_SERVICE
para ejecutar un
servicio:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
En el ejemplo anterior, se incluye un filtro de intents para MediaLibraryService
.
y, para retrocompatibilidad, la versión heredada MediaBrowserService
. El
el filtro de intents adicional habilita las apps cliente con la API de MediaBrowserCompat
para reconocer tu Service
.
Un MediaLibrarySession
te permite entregar tu biblioteca de contenido en un árbol.
con una raíz única MediaItem
. Cada MediaItem
en el árbol puede tener
cualquier cantidad de nodos MediaItem
secundarios Puedes entregar una raíz diferente o una
diferente, según la solicitud de la app cliente. Por ejemplo, el árbol que
volver a un cliente que busca una lista de elementos multimedia recomendados solo podría
contienen la raíz MediaItem
y un solo nivel de nodos MediaItem
secundarios,
mientras que el árbol que regresas
a una aplicación cliente diferente puede representar un
biblioteca completa de contenido.
Cómo crear un MediaLibrarySession
Un objeto MediaLibrarySession
Extiende la API de MediaSession
para agregar APIs de navegación de contenido. En comparación con el
Devolución de llamada MediaSession
,
la devolución de llamada MediaLibrarySession
agrega métodos como los siguientes:
onGetLibraryRoot()
para cuando un cliente solicite la raízMediaItem
de un árbol de contenidoonGetChildren()
para cuando un cliente solicita los elementos secundarios de unMediaItem
en el árbol de contenidoonGetSearchResult()
para cuando un cliente solicita resultados de búsqueda desde el árbol de contenido de un determinado consulta
Los métodos de devolución de llamada relevantes incluirán un LibraryParams
.
objeto con indicadores adicionales sobre el tipo de árbol de contenido que una app cliente
que le interesa.