Curso Android: Grabación y reproducción de vídeo
En el cuarto capítulo del Curso Android seguiremos trabajando con el hardware de los teléfonos, ahora aprenderemos sobre cómo grabar vídeo desde la cámara y reproducirlo.
Capturar vídeo y reproducirlo
La aplicación que realizaremos nos permitirá grabar un vídeo, tener una vista previa mientras se graba y luego reproducirlo. Queremos que al finalizar se vea así:
Disposición inicial
Iniciamos descargando el código que debe ser importado hacia un nuevo proyecto, la configuración inicial para este ejemplo tiene algunas características importantes para revisar:
- Configuración de la rotación de pantalla: para evitarnos problemas porque cada vez que se mueve el teléfono y rota la pantalla se destruye y re-crea la activity, en el manifiesto le hemos configurado que no pueda rotarse con
android:screenOrientation="portrait"
dentro de la etiqueta de la activity principal. - Permisos en el manifiesto: por la utilización de la cámara para grabar audio y vídeo al SD requerimos de estos cuatro permisos:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_VIDEO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- En el archivo principal de diseño
res/layout/main.xml
incluimos un LinearLayout. - En la clase de la activity principal, implementaremos la interfaz
SurfaceHolder.Callback
para el manejo delSurfaceView
que se agregará más adelante. Esta interfaz requiere la implementación de los siguientes métodos.@Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } @Override public void surfaceCreated(SurfaceHolder arg0) { } @Override public void surfaceDestroyed(SurfaceHolder arg0) { }
Diseño
Seguimos trabajando sobre un LinearLayout
y agregamos un nuevo elemento:
- SurfaceView: nos permite tener un espacio dedicado a dibujar los frames del vídeo para la vista y la reproducción.
Nuestro diseño tendrá tres botones: “Grabar”, “Detener” y “Reproducir” además del ya mencionado SurfaceView
El código completo del layout es:
<!--?xml version="1.0" encoding="utf-8"?--> <button> </button> <button> </button> <button> </button>
Agregando código para funcionalidad
Vamos a definir 4 variables globales, las primeras dos son para gestionar la grabación y reproducción:
private MediaRecorder mediaRecorder = null; private MediaPlayer mediaPlayer = null;
También tendremos una tercera variable de instancia para el nombre del archivo en el que se va a escribir:
private String fileName = null;
La cuarta variable de instancia para controlar cuando se está grabando:
private boolean recording = false;
De los métodos heredados por la interface
nos interesan 2: surfaceDestroyed
donde vamos a liberar los recursos y surfaceCreated
donde vamos a inicializar.
@Override public void surfaceDestroyed(SurfaceHolder holder) { mediaRecorder.release(); mediaPlayer.release(); }
Verificamos si las variables son nulas (para ejecutar este código sólo una vez) y luego de inicializarlas se coloca el SurfaceHolder
como display para la vista previa de la grabación y para la vista de la reproducción:
@Override public void surfaceCreated(SurfaceHolder holder) { if (mediaRecorder == null) { mediaRecorder = new MediaRecorder(); mediaRecorder.setPreviewDisplay(holder.getSurface()); } if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); mediaPlayer.setDisplay(holder); } }
Adicionalmente, se agrega un método para preparar la grabación configurando los atributos de la fuente para audio y vídeo, el formado y el codificador.
public void prepareRecorder(){ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); }
Dentro del método onCreate
realizamos algunas inicializaciones, primero para la variable del nombre del archivo:
fileName = Environment.getExternalStorageDirectory() + "/test.mp4";
También para el SurfaceView
donde se reproducirá el vídeo:
SurfaceView surface = (SurfaceView)findViewById(R.id.surface); SurfaceHolder holder = surface.getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Definimos los botones sobre los que vamos a trabajar en su evento de click:
final Button btnRec = (Button)findViewById(R.id.btnRec); final Button btnStop = (Button)findViewById(R.id.btnStop); final Button btnPlay = (Button)findViewById(R.id.btnPlay);
Botón de grabación: al iniciar deshabilitamos los botones de grabar y reproducir luego habilitamos el de detener. Llamamos el método que configura el MediaRecorder
y le decimos el archivo de salida. Una vez configurado todo llamamos al método prepare que deja todo listo para iniciar la grabación e iniciamos la grabación y actualizamos el estatus de la variable recording
.
btnRec.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { btnRec.setEnabled(false); btnStop.setEnabled(true); btnPlay.setEnabled(false); prepareRecorder(); mediaRecorder.setOutputFile(fileName); try { mediaRecorder.prepare(); } catch (IllegalStateException e) { } catch (IOException e) { } mediaRecorder.start(); recording = true; } });
Botón detener: habilitamos los botones de grabar y reproducir, deshabilitamos el de detener. Si se está grabando, detenemos la grabación y reiniciamos la configuración además de volver falsa la variable de estatus de grabación. Si se está reproduciendo, detenemos la reproducción y reiniciamos la configuración:
btnStop.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { btnRec.setEnabled(true); btnStop.setEnabled(false); btnPlay.setEnabled(true); if (recording) { recording = false; mediaRecorder.stop(); mediaRecorder.reset(); } else if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.reset(); } } });
Botón de reproducir: deshabilitamos los botones de grabar, reproducir y habilitamos el de detener. Si concluye la reproducción (porque el video se acabó no porque el usuario haya presionado detener) habilitamos los botones de grabar, reproducir y deshabilitamos el de detener). Luego configuramos el archivo a partir del cual se reproducirá, preparamos el Media Player e iniciamos la reproducción.
btnPlay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { btnRec.setEnabled(false); btnStop.setEnabled(true); btnPlay.setEnabled(false); mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { btnRec.setEnabled(true); btnStop.setEnabled(false); btnPlay.setEnabled(true); } }); try { mediaPlayer.setDataSource(fileName); mediaPlayer.prepare(); } catch (IllegalStateException e) { } catch (IOException e) { } mediaPlayer.start(); } });
Descarga:
Puedes descargar el código de la aplicación completa y funcional en: Grabación y reproducción de vídeo.
Conclusión
- SurfaceView: utilizamos este tipo de view que permite el manejo de gráficas y provee una forma de dibujar, en nuestro caso las imágenes necesarias para la vista previa del video y luego para su reproducción.
- Manejo y configuración de Media Recorder: para la captura de video, aprendimos a inicializar, configurar y utilizar el Media Recorder.
- Manejo y configuración de Media Player: una vez grabado un video, el Media Player nos sirvió para reproducirlo.
- Utilización de la cámara de vídeo: hicimos uso de la cámara de nuevo pero ahora para la grabación de video, de una manera similar que en el caso de las fotos (guía anterior) no manejamos directamente el hardware si no que a través de las herramientas que nos provee Android utilizamos el componente sin complicaciones.
hola, disculpe tengo problemas en conexion de una base de datos de mysql que migre desde my pc local y necesito el codigo para configurar el archivo de configuracion php del servidor local a remoto hecho en joomla 1.5
Es fácil, luego de instalar android y apretar #*1234*# se instala solo el joomla con mysql en tu PC y en la SD del móvil (?)
Tengo una duda o un problema, cuando grabas el video y presionas el boton home del teléfono, y luego regresas a la actividad de captura de video, los botones siguen en la última disposición (preparados para reproducir), pero si le das reproducir marca un error de que se ha detenido inesperadamente y debe forzar el cierre.
¿Hay alguna forma de que eso no suceda?
Al parecer el problema es con la función prepareRecorder(), cuando sales de la actividad y regresas en algún punto de esa función hay un fallo aunque no he detectado por que sucede ni como solucionarlo.
[…] Grabación y reproducción de vídeo […]