Un reproductor es el componente de tu app que facilita la reproducción de elementos multimedia.
La interfaz Player de Media3
establece un esquema para la funcionalidad que, por lo general, maneja un reproductor. Esto incluye lo siguiente:
- Afectar los controles de reproducción, como reproducir, pausar y buscar
- Consultar las propiedades del contenido multimedia que se está reproduciendo, como la posición de reproducción
- Administrar una playlist o una cola de elementos multimedia
- Configurar las propiedades de reproducción, como la reproducción aleatoria, la repetición, la velocidad y el volumen
- Renderizar video en la pantalla
Media3 también proporciona una implementación de la Player interfaz, llamada
ExoPlayer.
Una interfaz común entre componentes
Varios componentes de Media3 implementan la interfaz Player, por ejemplo:
| Componente | Notas de descripción y comportamiento |
|---|---|
ExoPlayer |
Es una API de reproductor multimedia y la implementación predeterminada de la interfaz Player. |
MediaController |
Interactúa con una MediaSession para enviar comandos de reproducción. Si
tu Player y MediaSession están en un
Service separado de la Activity o
Fragment donde reside la IU del reproductor, puedes asignar tu
MediaController como el reproductor de tu
componente de IU, como PlayerView o Player
Composable. Las llamadas a métodos de reproducción y de playlist se envían
a tu Player a través de tu MediaSession.
|
MediaBrowser |
Además de la funcionalidad que ofrece un
MediaController, interactúa con un
MediaLibrarySession para explorar el contenido multimedia disponible.
|
SimpleBasePlayer |
Es una implementación de Player que reduce la cantidad de métodos
que se deben implementar a un mínimo. Es útil cuando se usa un reproductor personalizado que deseas conectar a un MediaSession.
|
ForwardingSimpleBasePlayer |
Es una subclase SimpleBasePlayer diseñada para reenviar operaciones de reproducción
a otro Player y, al mismo tiempo, permitir las mismas
personalizaciones de comportamiento coherentes que SimpleBasePlayer. Usa
esta clase para suprimir o modificar operaciones de reproducción específicas.
|
RemoteCastPlayer |
Es una implementación de Player para controlar la reproducción en una app receptora de Cast remota.
|
CastPlayer |
Es una implementación de Player para controlar la reproducción de Cast local y remota.
|
Aunque una MediaSession no implementa la interfaz Player, requiere un Player cuando se crea una. Su propósito es proporcionar acceso al Player desde otros procesos o subprocesos.
Arquitectura de reproducción de Media3
Si tienes acceso a un Player, debes llamar a sus métodos directamente para enviar comandos de reproducción. Puedes anunciar tu reproducción y otorgar el control de reproducción de fuentes externas implementando una MediaSession. Estas fuentes externas implementan un MediaController, lo que facilita la conexión a una sesión multimedia y el envío de solicitudes de comandos de reproducción.
Cuando reproduces contenido multimedia en segundo plano, debes alojar tu sesión multimedia y tu reproductor dentro de un MediaSessionService o MediaLibraryService que se ejecute como un servicio en primer plano. Si lo haces, puedes separar el reproductor de la actividad en tu app que contiene la IU para el control de reproducción. Esto puede requerir que uses un controlador multimedia.
Player desempeña un papel clave
en la arquitectura de Media3.Estado del reproductor
El estado de un reproductor multimedia que implementa la interfaz Player consta principalmente de 4 categorías de información:
- Estado de reproducción
- Recupera con
getPlaybackState(). - Los valores de estado definidos por la interfaz son
STATE_IDLE,STATE_BUFFERING,STATE_READYySTATE_ENDED.
- Recupera con
- Playlist de elementos multimedia
- Una secuencia de instancias
MediaItempara la reproducción. - Recupera con
getCurrentTimeline() - Las instancias
Playerpueden proporcionar métodos de operación de playlist, como agregar o quitar unMediaItemy métodos convenientes, comogetCurrentMediaItem().
- Una secuencia de instancias
- Propiedades de reproducción/pausa, como las siguientes:
playWhenReady: Una indicación de si el usuario quiere que se reproduzca el contenido multimedia cuando sea posible o que permanezca en pausa- Motivo de supresión de reproducción:
Una indicación de por qué se suprime la reproducción, si corresponde, incluso si
playWhenReadyestrue isPlaying: Una indicación de si el reproductor está reproduciendo contenido actualmente, que solo serátruesi el estado de reproducción esSTATE_READY,playWhenReadyestruey la reproducción no se suprime
- Posición de reproducción, que incluye lo siguiente:
- Índice actual de elementos multimedia:
El índice del
MediaItemactual en la playlist. isPlayingAd: Una indicación de si se está reproduciendo un anuncio insertado.- Posición actual de la reproducción:
La posición actual de la reproducción dentro del
MediaItemo el anuncio insertado.
- Índice actual de elementos multimedia:
El índice del
Además, la interfaz Player permite acceder a las
pistas disponibles,
los metadatos multimedia,
la velocidad de reproducción,
el volumen y otras
propiedades auxiliares de la reproducción.
Escucha los cambios
Usa un Player.Listener
para escuchar los cambios en un Player. Consulta la documentación de ExoPlayer sobre
los eventos del reproductor para
obtener detalles sobre cómo crear y usar un objeto de escucha.
Ten en cuenta que la interfaz del objeto de escucha no incluye ninguna devolución de llamada para hacer un seguimiento de la progresión normal de la reproducción. Para supervisar continuamente el progreso de la reproducción, por ejemplo, para configurar una IU de barra de progreso, debes consultar la posición actual en intervalos adecuados.
Kotlin
fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs, )
Java
boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed( () -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
Controlar la reproducción
La interfaz Player ofrece muchas formas de manipular el estado y controlar la reproducción:
- Controles de reproducción básicos
como
play(),pause(),prepare()ystop(). - Operaciones de playlist como
addMediaItem()oremoveMediaItem(). - Búsqueda para cambiar el elemento o la posición actuales.
- Establece los modos de repetición y el modo aleatorio.
- Actualiza las preferencias de selección de pistas.
- Establece la velocidad de reproducción.
Implementaciones personalizadas de Player
Para crear un reproductor personalizado, puedes extender el
SimpleBasePlayer
incluido en Media3. Esta clase proporciona una implementación base de la interfaz Player para reducir la cantidad de métodos que debes implementar a un mínimo.
Comienza por anular el método getState(). Este método debe propagar el estado actual del reproductor cuando se lo llame, incluido lo siguiente:
- El conjunto de comandos disponibles
- Propiedades de reproducción, como si el reproductor debe comenzar a reproducirse cuando el estado de reproducción es
STATE_READY, el índice del elemento multimedia que se está reproduciendo y la posición de reproducción dentro del elemento actual
Kotlin
class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
Java
private static final class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer aplicará que el State se cree con una combinación válida de valores de estado. También controlará los objetos de escucha y los informará sobre los cambios de estado. Si necesitas activar manualmente una actualización de estado,
llama a invalidateState().
Más allá del método getState(), solo necesitas implementar los métodos que se usan para los comandos que tu reproductor declara como disponibles. Busca el método controlador anulable que corresponde a la funcionalidad que deseas implementar. Por ejemplo,
anula el método handleSeek()
para admitir operaciones como COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM
y COMMAND_SEEK_TO_NEXT_MEDIA_ITEM.
Modifica las implementaciones de Player
En lugar de crear un Player completamente personalizado, puedes usar
ForwardingSimpleBasePlayer para modificar el estado y el comportamiento de un
Player existente. Consulta la guía en la página Personalización para
obtener más detalles.