Custom ExoPlayer extra: Kotlin

Objetivo desse artigo é mostrar de forma prática como utilizar o framework Exoplayer da Google.

Por muito tempo tive dificuldade com esse framework devido a sua "complexidade" e falta de referências. Depois de apanhar muito, consegui utilizar em alguns projetos em produção. Resolvi compartilhar com os colegas devs para que não passem pelas mesmas dificuldades que passei de customização.

O que é o Exoplayer?

É um player alternativo ao MediaPlayer Api para tocar audios e videos locais ou pela internet, suporta streams e é de fácil customização (segundo o Google).

Por que e para que Exoplayer?

O ExoPlayer suporta recursos como transmissão dinâmica adaptativa incluindo DASH e SmoothStreaming, que não são suportados pelo MediaPlayer. E do contrário do MediaPlayer, é de fácil customização. Por isso é recomendado sua utilização.

Mãos a obra my Friends!!

Adicione ao build gradle:

implementation 'com.google.android.exoplayer:exoplayer:r2.4.4'fei

Exemplo do player sem customização.

Como customizar o player ? PlayerController

Primeiro vamos adicionar o exoPlayer a nossa view:

<com.google.android.exoplayer2.ui.SimpleExoPlayerView
android:id="@+id/simpleExoplayer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:controller_layout_id="@layout/exo_player_controllers"
app:player_layout_id="@layout/exo_player_background"
>
</com.google.android.exoplayer2.ui.SimpleExoPlayerView>

A propriedade app:controller_layout_id serve para adicionarmos o nosso custom controllers ao nosso player.

Vamos lá

<TextView
android:id="@+id/exo_position"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_weight="0.15"/>

<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@+id/exo_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:ad_marker_color="@color/colorAccent"
app:scrubber_color="@color/bgAlpha"
app:played_color="@color/colorAccent"
android:layout_weight="1"/>

<TextView
android:id="@+id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_weight="0.15"/>

<android.support.design.widget.FloatingActionButton
android:id="@id/exo_play"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="10dp"
style="@style/ExoMediaButton.Play"
android:layout_gravity="bottom|center"
android:background="@drawable/btn_app"
android:layout_marginBottom="20dp"/>

<android.support.design.widget.FloatingActionButton
android:id="@id/exo_pause"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="10dp"
style="@style/ExoMediaButton.Pause"
android:layout_gravity="bottom|center"
android:background="@drawable/btn_app"
android:layout_marginBottom="20dp"/>

exo_position: tempo corrente do aúdio/video, e colocamos em um TextView normal, conforme vai passando o tempo, ele se atualiza automaticamente.

exo_progress: barra de progresso, que nesse caso foi usado a DefaultTimeBar, onde podemos setar algumas propriedades de cores, como no exemplo acima.

Obs: Já tentei utilizar várias libs de barra de progresso customizadas e setar o id exo_progress porém nunca tive sucesso 👎. O problema é sempre o mesmo, o Exoplayer não consegue inflar a view por não ter compatibilidade.(CircleProgress, CircularProgressBar utilizadas sem sucesso).

exo_duration: tempo total do aúdio/video.

exo_play: botão de play. Utilizei um FloatingActionButton.

exo_pause: botão de pause, e da mesma forma que o play, também seta a imagem de pause.

Obs: sempre coloque o pause e o play um sobre o outro, pois quando um é pressionado o outro o substitui na mesma posição. Para as imagens do botão serem setadas utilizamos o style que a própria lib nos fornece.

Segue outros controles que podem ser customizados:

<item name="exo_artwork" type="id"/>
<item name="exo_duration" type="id"/>
<item name="exo_ffwd" type="id"/>
<item name="exo_next" type="id"/>
<item name="exo_overlay" type="id"/>
<item name="exo_prev" type="id"/>
<item name="exo_rew" type="id"/>
<item name="exo_shutter" type="id"/>
<item name="exo_subtitles" type="id"/>

Mudar o background

Era uma vez um Androider que tinha um player para fazer que era apenas o botão de play e pause, porém o background padrão do exoplayer é preto e ele não achou nada para poder mudar essa história…

Eis que por acaso foi encontrada uma propriedade do além:

app:player_layout_id="@layout/exo_player_background"

E colocamos esse layout abaixo para salvar a pátria!!!

<?xml version="1.0" encoding="utf-8"?>

<merge xmlns:android="http://schemas.android.com/apk/res/android">

<View android:id="@id/exo_controller_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

<FrameLayout android:id="@id/exo_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</merge>

Apenas deixei essas proprieadedes assim , vazias, sem nada, para retirar qualquer resquício de background. Caso alguém queira customizar esse background, fica a vontade.

Segue o link para saber mais sobre essa propriedades e outras mais para o layout do player.

Why Kotlin?

Esse projeto foi feito em kotlin, porém pode não estar com as melhores skills da linguagem, mas resolvi utilizar como uma maneira de estimular a galera a fazer o mesmo, pegar coisas que são bastante utilizadas no dia a dia dos amigos devs e passar para o amigo Kotlin e todo mundo aprende algo novo.

The End

O projeto está no Github. Ele toca um simples .mp3, qualquer dúvida chama e a gente, conversamos, e um PR no repositório sempre é bem vindo.