Screenshot: O aplicativo do YouTube Android
ExoPlayer é um reprodutor de mídia de nível de aplicativo construído sobre APIs de mídia de baixo nível no Android. O ExoPlayer tem uma série de vantagens sobre o MediaPlayer incorporado no Android. Ele suporta muitos dos mesmos formatos de mídia do MediaPlayer, além de formatos adaptativos, tais como DASH e SmoothStreaming. O ExoPlayer é altamente personalizável e extensível, tornando-o capaz de muitos casos de utilização avançada. É um projeto de código aberto usado pelas aplicações Google, incluindo YouTube e Google Play Movies & TV.
- Prerequisites
- O que você fará
- O que você vai precisar
- Apanhe o código
- Estrutura diretiva
- Importar o projecto inicial
- app/build.gradle
- Adicionar dependência ExoPlayer
- player-lib/build.gradle
- Adicionar o elemento PlayerView
- activity_player.xml
- PlayerActivity.java
- Criar um ExoPlayer
- PlayerActivity.java
- Criar um item de mídia
- PlayerActivity.java
- Tocar bem com o ciclo de vida da atividade
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Preparação final
- PlayerActivity.java
- Play audio
- Teste o ciclo de vida da atividade
- Tocar vídeo
- PlayerActivity.java
- PlayerActivity.java
- Selecção de faixa adaptável
- PlayerActivity.java
- Build um MediaItem adaptativo
- PlayerActivity.java
- Outros formatos de streaming adaptativo
- Ouvir
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Registe o seu ouvinte
- PlayerActivity.java
- PlayerActivity.java
- Vá mais fundo
- activity_player.xml
- activity_player.xml
- Personalize o comportamento
- activity_player.xml
- Personalizar a aparência
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- Sobre o estilo padrão
- activity_player.xml
- exo_player**_control_view.xml***
- Saiba mais
Prerequisites
- Conhecimento moderado do desenvolvimento do Android e Android Studio
O que você fará
- Criar uma instância
SimpleExoPlayer
, que prepara e reproduz mídia de uma variedade de fontes. - Integra o ExoPlayer com o ciclo de vida da atividade do aplicativo para suportar backgrounding, foregrounding e retomada da reprodução em um ambiente de uma ou várias janelas.
- Utilizar
MediaItem
s para criar uma lista de reprodução. - Tocar streams de vídeo adaptáveis, que adaptam a qualidade de mídia à largura de banda disponível.
- Registar ouvintes de eventos para monitorar o estado de reprodução e mostrar como os ouvintes podem ser usados para medir a qualidade da reprodução.
- Utilizar componentes ExoPlayer UI padrão, depois personalize-os ao estilo do seu aplicativo.
O que você vai precisar
- Android Studio versão 3.5 ou superior
- Um dispositivo Android com JellyBean (4.1) ou superior, idealmente com Nougat (7.1) ou superior, pois suporta múltiplas janelas.
Apanhe o código
Para começar, baixe o projeto Android Studio:
Download zip
Alternativamente, você pode clonar o repositório GitHub:
git clone https://github.com/googlecodelabs/exoplayer-intro.git
Estrutura diretiva
Clonar ou descompactar fornece uma pasta raiz (exoplayer-intro
), que contém uma pasta para cada etapa deste codelab, juntamente com todos os recursos necessários:
/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-00/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-01/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-02/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-03/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-04
As pastas exoplayer-codelab-N
(onde N
é 00
a 04
) contêm o estado final desejado de cada etapa deste codelab. Estes são projectos autónomos do Android Studio, que podem ser importados.
Importar o projecto inicial
- Iniciar Android Studio.
- Seleccionar ficheiro > Novo > Importar projecto*.*
- Importar o projecto inicial de
exoplayer-codelab-00
.
Screenshot: Estrutura do projeto ao importar
Após os acabamentos da construção, você vê dois módulos: o módulo app
(de tipo aplicação) e o módulo player-lib
(de tipo biblioteca). O módulo app
está na verdade vazio, tendo apenas um manifesto. Tudo do módulo player-lib
é fundido quando a aplicação é construída usando uma dependência de gradle em app/build.gradle
.
app/build.gradle
dependencies { implementation project(":player-lib")}
Seu media player Atividade é mantida no módulo player-lib
. A razão para mantê-la em um módulo de biblioteca separado é para que você possa compartilhá-la entre APKs visando diferentes plataformas, como celular e Android TV. Ele também permite que você tire proveito de recursos, como o Dynamic Delivery, que permite que o recurso de reprodução de mídia seja instalado somente quando o usuário precisar.
- Desenvolver e executar o aplicativo para verificar se tudo está bem. O aplicativo deve preencher a tela com um fundo preto.
Screenshot: Aplicação em branco a correr
Adicionar dependência ExoPlayer
ExoPlayer é um projecto de código aberto alojado no GitHub. Cada versão é distribuída através do jCenter, que é um dos repositórios de pacotes padrão usados pelo Android Studio e Gradle. Cada versão é unicamente identificada por uma string com o seguinte formato:
com.google.android.exoplayer:exoplayer:rX.X.X
Você pode adicionar o ExoPlayer ao seu projeto simplesmente importando suas classes e componentes UI. É bastante pequeno, tendo uma pegada encolhida de cerca de 70 a 300 kB, dependendo das características incluídas e formatos suportados. A biblioteca do ExoPlayer é dividida em módulos para permitir que os desenvolvedores importem apenas as funcionalidades de que necessitam. Para mais informações sobre a estrutura modular do ExoPlayer, veja Add ExoPlayer modules.
- Abrir o arquivo
build.gradle
do arquivoplayer-lib
module. - Adicionar as seguintes linhas à seção
dependencies
e sincronizar o projeto.
player-lib/build.gradle
dependencies { implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-dash:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'}
Adicionar o elemento PlayerView
- Abrir o arquivo de recurso de layout
activity_player.xml
do arquivoplayer-lib
module. - Pôr o cursor dentro do elemento
FrameLayout
> element. - Iniciar a digitação
<PlayerView
e deixar o Android Studio autocompletar o elementoPlayerView
. - Utilizar
match_parent
para owidth
eheight
. - Declarar a id como
video_view
.
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
Vá em frente, você se refere a este elemento UI como a visualização do vídeo.
- No
PlayerActivity
, agora você precisa encontrar a visualização do vídeo para que você possa configurá-lo corretamente no métodoonCreate
da atividade.
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- Adicionar o campo de membro
playerView
à sua classePlayerActivity
. Certifique-se de que o tipo de vista éPlayerView
.
Note: Use o recurso Quick Fix no Android Studio para adicionar um campo de membro automaticamente. Lembre-se de definir o tipo para
PlayerView
rather than the default
View
>
Screenshot: Quick fix menu for making a member field
Criar um ExoPlayer
Para reproduzir streaming media, você precisa de um objeto ExoPlayer
. A maneira mais simples de criar um é usar a classe SimpleExoPlayer.Builder
. Como o nome sugere, isto usa o padrão do construtor para construir uma SimpleExoPlayer
instância.
SimpleExoPlayer
é uma implementação conveniente e para todos os fins da ExoPlayer
interface.
Adicionar um método privado initializePlayer
para criar o seu objecto SimpleExoPlayer
.
PlayerActivity.java
private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}
Criar um SimpleExoPlayer.Builder
usando o seu contexto, depois ligue para build
para criar o seu objecto SimpleExoPlayer
. Isto é então atribuído a player
, que você precisa declarar como um campo de membro. Você então usa playerView.setPlayer
para ligar o player
à sua visão correspondente.
Criar um item de mídia
Seu player
agora precisa de algum conteúdo para reproduzir. Para isso, você cria um MediaItem
. Existem muitos tipos diferentes de MediaItem
, mas você começa criando um para um arquivo MP3 na internet.
A maneira mais simples de criar um MediaItem
é usar MediaItem.fromUri
, que aceita o URI de um arquivo de mídia. Adicione o MediaItem
ao player
usando player.setMediaItem
.
- Adicione o seguinte código a
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}
Nota que R.string.media_url_mp3
é definida como https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 em strings.xml
.
Tocar bem com o ciclo de vida da atividade
Nossa player
pode monopolizar muitos recursos, incluindo memória, CPU, conexões de rede e codecs de hardware. Muitos desses recursos estão em falta, particularmente para os codecs de hardware, onde pode haver apenas um. É importante que você libere esses recursos para que outros aplicativos sejam usados quando você não os estiver usando, como quando seu aplicativo for colocado em segundo plano.
Clique de outra forma, o ciclo de vida do seu player deve ser vinculado ao ciclo de vida do seu aplicativo. Para implementar isto, você precisa substituir os quatro métodos de PlayerActivity
: onStart
, onResume
, onPause
, e onStop
.
- Com
PlayerActivity
abrir, clique no menu Código > Substituir métodos…. - Seleccionar
onStart
,onResume
,onPause
, eonStop
. - Initializar o jogador no nível
onStart
ouonResume
Callback dependendo do nível da API.
PlayerActivity.java
@Overridepublic void onStart() { super.onStart(); if (Util.SDK_INT >= 24) { initializePlayer(); }}@Overridepublic void onResume() { super.onResume(); hideSystemUi(); if ((Util.SDK_INT < 24 || player == null)) { initializePlayer(); }}
Android API nível 24 e superior suporta múltiplas janelas. Como sua aplicação pode ser visível, mas não ativa no modo janela dividida, você precisa inicializar o jogador em onStart
. Android API nível 24 e inferior requer que você espere o máximo de tempo possível até você pegar recursos, então você espera até onResume
antes de inicializar o player.
- Adicionar o método
hideSystemUi
>
PlayerActivity.java
@SuppressLint("InlinedApi")private void hideSystemUi() { playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);}
hideSystemUi
é um método de ajuda chamado em onResume
, que permite que você tenha uma experiência em tela cheia.
- Largar recursos com
releasePlayer
(que você cria em breve) emonPause
eonStop
.
PlayerActivity.java
@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}
Com API nível 24 e inferior, não há garantia de onStop
ser chamado, então você tem que liberar o jogador o mais cedo possível em onPause
. Com a API Nível 24 e superior (que trouxe o modo multi- e split-window), onStop
é garantido que será chamado. No estado pausado, sua atividade ainda é visível, então você espera para liberar o player até onStop
.
Agora você precisa criar um método releasePlayer
, que libera os recursos do player e o destrói.
- Adicionar o seguinte código à atividade:
PlayerActivity.java
private boolean playWhenReady = true;private int currentWindow = 0;private long playbackPosition = 0;private void releasePlayer() { if (player != null) { playWhenReady = player.getPlayWhenReady(); playbackPosition = player.getCurrentPosition(); currentWindow = player.getCurrentWindowIndex(); player.release(); player = null; }}
Antes de soltar e destruir o player, armazene as seguintes informações:
- Tocar/pausar estado usando
getPlayWhenReady
. - Posição atual de reprodução usando
getCurrentPosition
. - Índice da janela atual usando
getCurrentWindowIndex
. Para mais informações sobre janelas, veja Linha do tempo.
Isso permite retomar a reprodução de onde o usuário parou. Tudo o que você precisa fazer é fornecer esta informação de estado quando você inicializa seu player.
Preparação final
Tudo o que você precisa fazer agora é fornecer a informação de estado que você salvou em releasePlayer
ao seu player durante a inicialização.
- Adicionar o seguinte a
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}
Aqui está o que está a acontecer:
-
setPlayWhenReady
diz ao leitor se deve começar a reproduzir assim que todos os recursos para reprodução tenham sido adquiridos. PorqueplayWhenReady
é inicialmentetrue
, a reprodução começa automaticamente na primeira vez que o aplicativo é executado. -
seekTo
diz ao player para procurar uma determinada posição dentro de uma janela específica. AmboscurrentWindow
eplaybackPosition
são inicializados a zero para que a reprodução comece desde a primeira vez que o aplicativo for executado. -
prepare
diz ao player para adquirir todos os recursos necessários para a reprodução.
Play audio
Finalmente, você está pronto! Inicie o aplicativo para reproduzir o arquivo MP3 e veja a arte embutida.
Screenshot: O aplicativo tocando uma única faixa.
Teste o ciclo de vida da atividade
Teste se o aplicativo funciona em todos os diferentes estados do ciclo de vida da atividade.
- Inicie outro aplicativo e coloque seu aplicativo em primeiro plano novamente. Ele retoma na posição correta?
- Pausa o aplicativo, e move-o para o segundo plano e depois para o primeiro plano novamente. Ele se mantém em pausa quando em segundo plano em estado de pausa?
- Rotate o aplicativo. Como ele se comporta se você mudar a orientação de retrato para paisagem e vice-versa?
Tocar vídeo
Se você quiser reproduzir vídeo, é tão fácil quanto modificar o item de mídia URI para um arquivo MP4.
- Mude o URI no ficheiro
initializePlayer
paraR.string.media_url_mp4
. - Comece a aplicação novamente e teste o comportamento depois de ser reproduzido em segundo plano também.
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }
O ficheiro PlayerView
faz tudo. Ao invés da arte, o vídeo é renderizado em tela cheia.
Screenshot: O aplicativo tocando vídeo.
Você é o máximo! Você acabou de criar um aplicativo para streaming de mídia em tela cheia no Android, completo com gerenciamento de ciclo de vida, estado salvo e controles UI!
Seu aplicativo atual reproduz um único arquivo de mídia, mas e se você quiser reproduzir mais de um arquivo de mídia, um após o outro? Para isso, você precisa de uma playlist.
Playlists podem ser criadas adicionando mais MediaItem
s ao seu player
usando addMediaItem
. Isto permite uma reprodução sem problemas e o buffer é manipulado em segundo plano para que o usuário não veja um spinner de buffer ao alterar itens de mídia.
- Adicionar o seguinte código para
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }
Verifica como os controles do player se comportam. Você pode usar e para navegar na seqüência de itens de mídia.
Screenshot: Controles de reprodução mostrando um botão próximo e anterior
Isso é muito útil! Para mais informações, veja a documentação do desenvolvedor sobre Itens de Mídia e Listas de Reprodução, e este artigo sobre a API da Playlist.
Audaptive streaming é uma técnica para streaming de mídia variando a qualidade do stream com base na largura de banda disponível na rede. Isto permite ao usuário experimentar a melhor qualidade de mídia que sua largura de banda permite.
Tipicamente, o mesmo conteúdo de mídia é dividido em várias faixas com diferentes qualidades (bit rates e resoluções). O leitor escolhe uma faixa com base na largura de banda disponível na rede.
Cada faixa é dividida em pedaços de uma determinada duração, normalmente entre 2 e 10 segundos. Isto permite ao jogador alternar rapidamente entre as faixas conforme a largura de banda disponível. O leitor é responsável por juntar estes pedaços para uma reprodução sem falhas.
Selecção de faixa adaptável
No coração do streaming adaptável está a selecção da faixa mais apropriada para o ambiente actual. Atualize seu aplicativo para reproduzir streaming adaptativo usando a seleção de faixa adaptativa.
- Atualizar
initializePlayer
com o seguinte código:
PlayerActivity.java
private void initializePlayer() { if (player == null) { DefaultTrackSelector trackSelector = new DefaultTrackSelector(this); trackSelector.setParameters( trackSelector.buildUponParameters().setMaxVideoSizeSd()); player = new SimpleExoPlayer.Builder(this) .setTrackSelector(trackSelector) .build(); } // Remove or comment out. // player = new SimpleExoPlayer.Builder(this).build(); }
Primeiro, crie um DefaultTrackSelector
, que é responsável por escolher as faixas no item de mídia. Depois, diga ao seu trackSelector
para escolher apenas faixas de definição padrão ou inferior – uma boa maneira de salvar os dados do seu usuário às custas da qualidade. Finalmente, passe o seu trackSelector
ao seu construtor para que ele seja utilizado na construção da SimpleExoPlayer
instância.
Build um MediaItem adaptativo
DASH é um formato de streaming adaptativo amplamente utilizado. Para fazer streaming de conteúdo DASH, você precisa criar um MediaItem
como antes. No entanto, desta vez, devemos usar um MediaItem.Builder
em vez de fromUri
.
Isto porque fromUri
usa a extensão de arquivo para determinar o formato de mídia subjacente, mas o nosso DASH URI não tem uma extensão de arquivo, então devemos fornecer um tipo MIME de APPLICATION_MPD
ao construir o MediaItem
.
- Atualizar
initializePlayer
da seguinte forma:
PlayerActivity.java
- Reiniciar a aplicação e ver o streaming de vídeo adaptável com o DASH em acção. É muito fácil com ExoPlayer!
Outros formatos de streaming adaptativo
HLS (MimeTypes.APPLICATION_M3U8
) e SmoothStreaming (MimeTypes.APPLICATION_SS
) são outros formatos de streaming adaptativo comumente usados, ambos suportados pelo ExoPlayer. Para mais informações sobre a construção de outras fontes de mídia adaptativas, veja a demonstração do ExoPlayer app.
Nos passos anteriores, você aprendeu como fazer streaming de streams progressivos e adaptativos. O ExoPlayer está fazendo muito trabalho para você nos bastidores, incluindo o seguinte:
- Alocar memória
- Baixar arquivos do recipiente
- Extrair metadados do recipiente
- Decifrar dados
- Renderizar vídeo, áudio e texto para a tela e alto-falantes
Por vezes, é útil saber o que o ExoPlayer está fazendo em tempo de execução para entender e melhorar a experiência de reprodução para seus usuários.
Por exemplo, você pode querer refletir as mudanças de estado de reprodução na interface do usuário fazendo o seguinte:
- Exibir um spinner de carregamento quando o player entra em estado de buffering
- Exibir uma overlay com opções de “watch next” quando a faixa tiver terminado
ExoPlayer oferece várias interfaces de ouvintes que fornecem callbacks para eventos úteis. Você usa um ouvinte para registrar em que estado o player está.
Ouvir
- Declare um membro privado do tipo
PlaybackStateListener
noPlayerActivity
. - Criar uma constante
TAG
, que você usa para registrar mais tarde.
PlayerActivity.java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
- Instanciar a
playbackStateListener
no início deonCreate
(ainda não compilará, mas você corrigirá isso em breve).
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
- Utilizar Quick Fix para criar a classe interna
PlaybackStateListener
automaticamente.
Screenshot: Quick Fix menu para criar uma classe ausente
- Implementar a interface
Player.EventListener
. Isto é usado para informar sobre eventos importantes do player, incluindo erros e mudanças de estado de reprodução. - Override
onPlaybackStateChanged
adicionando o seguinte código:
PlayerActivity.java
private class PlaybackStateListener implements Player.EventListener { @Override public void onPlaybackStateChanged(int playbackState) { String stateString; switch (playbackState) { case ExoPlayer.STATE_IDLE: stateString = "ExoPlayer.STATE_IDLE -"; break; case ExoPlayer.STATE_BUFFERING: stateString = "ExoPlayer.STATE_BUFFERING -"; break; case ExoPlayer.STATE_READY: stateString = "ExoPlayer.STATE_READY -"; break; case ExoPlayer.STATE_ENDED: stateString = "ExoPlayer.STATE_ENDED -"; break; default: stateString = "UNKNOWN_STATE -"; break; } Log.d(TAG, "changed state to " + stateString); }}
onPlaybackStateChanged
é chamado quando o estado de reprodução muda. O novo estado é dado pelo parâmetro playbackState
O leitor pode estar num dos seguintes quatro estados:
State |
Descrição |
> |
O leitor foi instanciado, mas ainda não foi preparado. |
|
O jogador não é capaz de jogar a partir da posição atual porque não foram armazenados dados suficientes. |
|
O jogador é capaz de jogar imediatamente a partir da posição atual. Isto significa que o leitor começará a reproduzir media automaticamente se a propriedade do leitor WhenReady for |
|
O player terminou de tocar a mídia. |
Registe o seu ouvinte
Para ter as suas chamadas de retorno, você precisa registrar o seu playbackStateListener
com o player. Faça isso em initializePlayer
.
- Registre o ouvinte antes que a reprodução seja preparada.
PlayerActivity.java
private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}
Again, você precisa arrumar para evitar referências penduradas do player que poderiam causar um vazamento de memória.
- Remover o ouvinte em
releasePlayer
:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- Abrir logcat e executar o app.
- Utilizar os controlos UI para procurar, pausar e retomar a reprodução. Você deve ver a mudança de estado da reprodução nos logs.
Vá mais fundo
ExoPlayer oferece vários outros ouvintes, que são úteis para entender a experiência de reprodução do usuário. Existem ouvintes para áudio e vídeo, assim como um AnalyticsListener
, que contém as chamadas de retorno de todos os ouvintes. Alguns dos métodos mais importantes são os seguintes:
-
onRenderedFirstFrame
é chamado quando o primeiro frame de um vídeo é renderizado. Com isto, você pode calcular quanto tempo o usuário teve que esperar para ver o conteúdo significativo na tela. -
onDroppedVideoFrames
é chamado quando os frames do vídeo são descartados. Frames perdidos indicam que a reprodução é janky e a experiência do usuário provavelmente será pobre. -
onAudioUnderrun
é chamada quando houve uma subexecução de áudio. Underruns causam falhas audíveis no som e são mais perceptíveis que quedas de quadros de vídeo.
AnalyticsListener
podem ser adicionados a player
com addAnalyticsListener
. Há métodos correspondentes para os ouvintes de áudio e vídeo também.
Pense sobre quais eventos são importantes para o seu aplicativo e seus usuários. Para mais informações, consulte Ouvindo para eventos de player. É isso para ouvintes de eventos!
Até agora, você tem usado o ExoPlayer’s PlayerControlView
para exibir um controlador de reprodução para o usuário.
Screenshot: Controlador de reprodução padrão
E se você quiser alterar a funcionalidade ou o visual e a sensação desses controles? Felizmente, estes controles são altamente personalizáveis.
A primeira personalização simples é não usar o controlador de forma alguma. Isto pode ser feito facilmente usando o atributo use_controller
no elemento PlayerView
dentro de activity_player.xml
.
- Set
use_controller
afalse
e o controle não aparece mais:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
- Adicionar o seguinte espaço de nomes ao seu
FrameLayout
:
activity_player.xml
<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">
Tente agora.
Personalize o comportamento
PlayerControlView
tem vários atributos que afectam o seu comportamento. Use show_timeout
, fastforward_increment
, e rewind_increment
para personalizar o comportamento do controlador.
- Remover
app:use_controller="false"
. - Mudar a vista do jogador para usar
show_timeout
,fastforward_increment
erewind_increment
:
>
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="10000" app:fastforward_increment="30000" app:rewind_increment="30000"/>
- O valor
show_timeout
diz aoPlayerView
o atraso em milissegundos antes do controle ser escondido após a última interação do usuário com ele. - Os valores
fastforward_increment
erewind_increment
dizem ao jogador o tempo em milissegundos para saltar para a frente ou para trás quando o utilizador pressiona os botões de avanço rápido ou retrocesso.
Os atributos do PlayerControlView
também podem ser programados.
Personalizar a aparência
Bem, isso é um bom começo. Mas e se você quiser que o PlayerControlView
tenha uma aparência diferente ou mudar quais botões são exibidos? A implementação de PlayerControlView
não assume que existam botões, por isso é fácil removê-los e adicionar novos.
Consulte como você pode personalizar o PlayerControlView
.
- Criar um novo arquivo de layout
custom_player_control_view.xml
na pastaplayer-lib/res/layout/
. - No menu de contexto da pasta de layout, escolha New – Layout resource file e nomee-o
custom_player_control_view.xml
.
Screenshot: O ficheiro de layout para a vista de controlo do leitor foi criado.
- Copiar o ficheiro de layout original daqui para
custom_player_control_view.xml
. - Remover os elementos
ImageButton
com o id@id/exo_prev
e@id/exo_next
.
Para usar o seu layout personalizado, precisa de definir o atributo app:controller_layout_id
do elemento PlayerView
no ficheiro activity_player.xml
- Utilize o ID do layout do seu ficheiro personalizado como no seguinte código snippet:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:controller_layout_id="@layout/custom_player_control_view"/>
- Inicie a aplicação novamente. A vista de controlo do jogador já não tem os botões anterior e seguinte.
Screenshot: Vista de controlo personalizada do leitor sem os botões anterior e seguinte
Pode aplicar as alterações que quiser no ficheiro de layout. Por padrão, as cores do tema do Android são escolhidas. Você pode substituir isto para combinar com o design do seu app.
- Adicionar um atributo
android:tint
a cadaImageButton
element:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- Mude todos
android:textColor
Atributos que você encontra no seu arquivo personalizado para a mesma cor:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position" android:textColor="#FF00A6FF"/><TextView android:id="@id/exo_duration" android:textColor="#FF00A6FF"/>
- Executar o aplicativo. Agora você tem lindos e coloridos componentes UI!
Screenshot: Botões coloridos e visualização de texto
Sobre o estilo padrão
Você acabou de criar um arquivo de layout personalizado e referenciou-o usando controller_layout_id
em activity_player.xml
.
Outra abordagem é sobrepor o arquivo de layout padrão que PlayerControlView
usa. O código fonte de PlayerControlView
nos diz que ele usa R.layout.exo_player_control_view
para layout. Se criar o nosso próprio ficheiro de layout com o mesmo nome de ficheiro, o ficheiro PlayerControlView
utiliza o seu ficheiro em vez disso.
- Remover o atributo
controller_layout_id
que acabou de adicionar. - Eliminar o ficheiro
custom_player_control_view.xml
.
O ficheiro PlayerView
em activity_player.xml
deve agora ter o seguinte aspecto:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- Criar um ficheiro chamado
exo_player_control_view.xml
na pastares/layout
do módulo da sua bibliotecaplayer-lib
. - Inserir o seguinte código em
exo_player_control_view.xml
para adicionar um botão play, um botão de pausa, e umImageView
com um logótipo:
exo_player**_control_view.xml***
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layoutDirection="ltr" android:background="#CC000000" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="4dp" android:orientation="horizontal"> <ImageButton android:id="@id/exo_play" style="@style/ExoMediaButton.Play"/> <ImageButton android:id="@id/exo_pause" style="@style/ExoMediaButton.Pause"/> </LinearLayout> <ImageView android:contentDescription="@string/logo" android:src="@drawable/google_logo" android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>
Isto demonstra como pode adicionar os seus próprios elementos aqui e misturá-los com elementos de controlo padrão. ExoPlayerView
agora usa o seu controlo personalizado e toda a lógica para esconder e mostrar quando interagir com o controlo é preservada.
Congratulações! Você aprendeu muito sobre a integração do ExoPlayer com seu app.