Um app que reproduz mídia requer componentes de interface do usuário para exibir mídia e controlar a reprodução. A biblioteca Media3 inclui um módulo de interface que contém vários componentes de interface. Para depender do módulo da interface, adicione a seguinte dependência:
Kotlin
implementation("androidx.media3:media3-ui:1.3.1")
Groovy
implementation "androidx.media3:media3-ui:1.3.1"
O componente mais importante é a PlayerView
, uma visualização para reproduções de mídia.
PlayerView
mostra o vídeo, as legendas e a capa do álbum durante a reprodução, além
dos controles de reprodução.
PlayerView
tem um método setPlayer
para anexar e remover (transmitindo null
) instâncias de jogador.
Visualização do player
PlayerView
pode ser usado para reproduções de vídeo e áudio. Ela renderiza
vídeo e legendas no caso de reprodução de vídeo, além de poder exibir artes
incluídas como metadados em arquivos de áudio. Você pode incluí-lo nos arquivos de layout
como qualquer outro componente de interface. Por exemplo, um PlayerView
pode ser incluído
com este XML:
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:show_buffering="when_playing"
app:show_shuffle_button="true"/>
O snippet acima ilustra que PlayerView
fornece vários
atributos. Esses atributos podem ser usados para personalizar o comportamento e a
aparência da visualização. A maioria desses atributos tem métodos setter
correspondentes, que podem ser usados para personalizar a visualização no momento da execução. O Javadoc
PlayerView
lista esses atributos e métodos setter em
mais detalhes.
Depois que a visualização é declarada no arquivo de layout, ela pode ser pesquisada no
método onCreate
da atividade:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... playerView = findViewById(R.id.player_view) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... playerView = findViewById(R.id.player_view); }
Quando um player é inicializado, ele pode ser anexado à visualização chamando
setPlayer
:
Kotlin
// Instantiate the player. val player = ExoPlayer.Builder(context).build() // Attach player to the view. playerView.player = player // Set the media item to be played. player.setMediaItem(mediaItem) // Prepare the player. player.prepare()
Java
// Instantiate the player. player = new ExoPlayer.Builder(context).build(); // Attach player to the view. playerView.setPlayer(player); // Set the media item to be played. player.setMediaItem(mediaItem); // Prepare the player. player.prepare();
Escolha um tipo de superfície
O atributo surface_type
do PlayerView
permite definir o tipo de superfície
usado para reprodução de vídeo. Além dos valores spherical_gl_surface_view
(que é um valor especial para reprodução de vídeo esférico) e
video_decoder_gl_surface_view
(que é para renderização de vídeo usando renderizadores
de extensão), os valores permitidos são surface_view
, texture_view
e none
. Se
a visualização for apenas para reprodução de áudio, none
precisará ser usado para evitar a necessidade
de criar uma superfície, porque isso pode ser caro.
Se a visualização for para reprodução normal de vídeos, use surface_view
ou texture_view
. SurfaceView
tem vários benefícios em relação a TextureView
para
reprodução de vídeos:
- Um consumo de energia significativamente menor em muitos dispositivos.
- Tempo para a renderização do frame mais precisa, resultando em uma reprodução de vídeo mais suave.
- Compatível com saída de vídeo HDR de maior qualidade em dispositivos compatíveis.
- Compatibilidade com saída segura ao reproduzir conteúdo protegido por DRM.
- Capacidade de renderizar conteúdo de vídeo na resolução máxima da tela em dispositivos Android TV que melhoram a camada de interface.
SurfaceView
precisa ter preferência sobre TextureView
sempre que possível.
Use TextureView
apenas se SurfaceView
não atender às suas necessidades. Um
exemplo é quando as animações suaves ou a rolagem da superfície de vídeo são necessárias
antes do Android 7.0 (nível 24 da API), conforme descrito nas observações abaixo. Para
esse caso, é preferível usar TextureView
somente quando SDK_INT
for anterior
a 24 (Android 7.0) e SurfaceView
caso contrário.
Navegação com botão direcional no Android TV
O controle remoto do Android TV tem um botão direcional que envia comandos que
chegam como evento de tecla às dispatchKeyEvent(KeyEvent)
da Activity
. Os
aspectos precisam ser delegados à visualização do jogador:
Kotlin
override fun dispatchKeyEvent(event: KeyEvent?): Boolean{ return playerView.dispatchKeyEvent(event!!) || super.dispatchKeyEvent(event) }
Java
@Override public boolean dispatchKeyEvent(KeyEvent event) { return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); }
Solicitar o foco para a visualização do player é importante para navegar pelos controles
de reprodução e pular anúncios. Considere solicitar o foco em onCreate
do
Activity
:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... playerView.requestFocus() // ... }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... playerView.requestFocus(); // ... }
Se você estiver usando o Compose no Android TV, será necessário tornar o AndroidView
focável e delegar o evento transmitindo o parâmetro do modificador para
AndroidView
adequadamente:
AndroidView(
modifier = modifier
.focusable()
.onKeyEvent { playerView.dispatchKeyEvent(it.nativeKeyEvent) },
factory = { playerView }
)
Substituir drawables
PlayerView
usa PlayerControlView
para exibir os controles de reprodução e a barra de progresso. Os drawables usados por PlayerControlView
podem
ser substituídos por drawables com os mesmos nomes definidos no app. Consulte
o Javadoc PlayerControlView
(link em inglês) para uma lista de drawables de controle que
podem ser substituídos.
Mais personalização
Quando uma personalização além da descrita acima for necessária, esperamos que os desenvolvedores de apps implementem os próprios componentes de interface em vez de usar os fornecidos pelo módulo de interface do Media3.