Android: Gestión de orientación con VideoView

Hace no mucho tuve que escuchar como un “experto” en Android decía que nunca íbamos a tener que reproducir vídeos de forma nativa en una aplicación. Para mí suerte o desgracia eso no era más que una gran mentira. No sé si mucha gente tiene que pelearse a diario con la reproducción de vídeos pero en mi caso se ha convertido en mi pan de cada día. Poco a poco he tenido que ir armando el pequeño puzzle e intentar crearme las piezas que me permitieran reutilizar mi trabajo de una aplicación a otra. Aquí está un pequeño resumen de lo que he sacado en claro, y espero que ayude a alguien.

Haciendo un pequeño resumen… lo que aquí se cuenta es básicamente:

  1. Cómo crear un VideoView customizado
  2.  MediaController customizado
  3. Crear un fragment que los contenga
  4. Modificar el tamaño del vídeo sin detenerlo
  5. Permitir el dimensionamiento del vídeo en función de la orientación del dispositivo

VideoView Customizado

El hecho de implementar un VideoView que extienda del widget VideoView nativo de Android nos permitirá tener un mayor control del objeto. En este caso la lógica de reproducción del vídeo será manejada desde el propio objeto. Además dará feedback al usuario a través de un ProgressDialog de cargando que se quitará cuando se haya realizado correctamente la carga del vídeo o en caso de error. Para ello implementaremos los Listener de eventos de vídeo. Además también crearemos un Listener interno que nos permita informar a la actividad del estado de la reproducción.

Para reproducir tanto vídeos como audios se utiliza el MediaPlayer, por lo que es importante saber los estados por los que puede pasar la reproducción y así poder gestionarla de forma más eficiente.  Para más información sobre el MediaPlayer ir a http://developer.android.com/guide/topics/media/mediaplayer.html. En este ejemplo vamos a implementar la interfaz onCompletion para manejar el evento de fin de vídeo, onPrepared para gestionar el player cuando el vídeo esté cargado y onError para gestionar los posibles errores.

A continuación implementamos el método que hará de interfaz con el fragment y que será el encargado de iniciar el VideoView.

Por último, implementamos el ciclo de vida de una actividad para asegurarnos de que el vídeo se para al pararse o destruirse la actividad que lo controla y que al volver de background no se reinicia sino que comienza desde el momento en el que estaba.

 MediaController Customizado

Igual que hemos hecho con el VideoView vamos a customizar el MediaController. En mi caso esta customización me ha servido principalmente para tener una mayor facilidad a la hora de modificar la apariencia del player y sobretodo para poder darle las dimensiones y la posición que yo quería de una forma muy sencilla sencilla. La customización del player la encontré buscando en StackOverflow post

Y para entender un poco mejor como utilizarlo consulté el siguiente blog

 Integramos en un Fragment

Lo primero que tendremos que hacer será crear la interfaz que se compondrá del CustomVideoView y un FrameLayout donde insertaremos el CustomMediaPlayer. Desde aquí podemos asignar las dimensiones iniciales de nuestros elementos, y determinar la posición del MediaController con referencia al video.

Una vez creada la interfaz implementamos el fragment. Lo primero que tenemos que hacer es implementar las interfaces que creamos en el CustomVideoView y el CustomMediaController para poder controlar la reproducción desde el propio Fragment. Además implementaremos la interfaz OnTouchListener para mostrar el MediaController al pulsar sobre el video, y pasados 5 segundos se ocultará automáticamente.

Inicializamos el Fragment con los valores que se le pasan como parámetro para lo que sobreescribimos los métodos onCreate y onCreateView

Además habrá que implementar tanto el ciclo de vida del Fragment como las interfaces que se definieron para el MediaController y el VideoView

  • Ciclo de vida

  •  Interfaz CustomVideoView

  • Interfaz MediaController

 Modificar tamaño del vídeo

Para modificar el tamaño del vídeo sin que esto influya en la reproducción del mismo tendremos que seguir 3 pasos:

1. Crear un método que nos permita modificar las dimensiones del video

2. Crear un método en el VideoView customizado en el que se asigne el tamaño de la pantalla basado en el ancho y un alto.

3. Modificar el Manifiest para que la actividad que contenga el video no se vea afectada por los cambios en la orientación, tamaño de pantalla ni teclado.

Dimensionamiento en función de la orientación

Por último pero no menos importante, modificaremos el  tamaño del vídeo en función de la orientación del dispositivo sobreescribiendo el método onConfigurationChanged del Fragment.

 Integración de la solución

Ya sólo falta darle un poco de sentido a esto y hacerlo funcionar… así que vamos a insertarlo dentro de una actividad con un par de botones que nos permitan probar ambas funcionalidades, modificación de tamaño y de orientación. El botón de modificación de orientación servirá sobretodo en caso de que estemos probando en simulador, ya que también se modificará el tamaño al modificar la orientación del teléfono.

Cómo en el caso del Fragment lo primero que tenemos que hacer es crear el layout. En este caso he decidido incluir un NavigationDrawer con vistas a crear un playlist que se mostrará en el menú. Para un caso más simple sería suficiente con un el main content view.

Inicializamos la vista, creamos el PlayerFragment e insertándolo en el layout.

Creamos la funcionalidad de los botones:

– Orientación:

Fuerza a que se cambie la orientación, por lo que llama automáticamente al onConfigurationChanged. Esto es sobretodo si lo probamos en el simulador para hacerlo más sencillo. Pero hay que tener en cuenta que al forzarlo se pierde el cambio por acelerómetro.

 

– Tamaño:

Modifica el tamaño del video y la posición del mismo. Si ya estaba en pequeño se modifica de tal manera que se adapte al ancho del padre y a su propia altura. Si por el contrario estuviera en las dimensiones iniciales (ancho:MATCH_PARENT, alto: WRAP_CONTENT) se le asigna un tamaño menor (320, 180).

Gestionamos los cambios de orientación:

Si el vídeo estaba en grande y cambiamos la orientación a LANDSCAPE se ocultarán los botones y el vídeo pasará a pantalla completa. Si por el contrario el vídeo estaba en su versión pequeña se conservará el tamaño del vídeo.

En el caso de la orientación LANDSCAPE y los botones ocultos se podrá volver a la posición vertical pulsando atrás:

 

Lo dicho… que espero que esto le ayude a alguien y disponible en GitHub!

Gracias a Don Roberto Marco por su inestimable ayuda durante la clase de Android… instalando el plugin de maquetado de código!

Deja un comentario