Bienvenidos sean a este post, hoy hablaremos sobre la clase MediaRecorder la cual nos facilitara la posibilidad de capturar audio y video en distintos formatos., como la mayoria de los dispositivos dispone de un microfono para capturar audio podremos probarlos en equipos reales pero esta funcion no fue integrada en los emuladores (aunque no es del todo cierto). Pasemos a ver algunos metodos disponibles de la clase MediaRecorder:

  • setAudioSource(int audio_source), dispositivo que se utilizara como fuente de sonido, usualmente es MediaRecorder.AudioSource.MIC
  • setOutputFile(String fichero), nombra al fichero de salida
  • setOutputFormat(int output_format), indica el formato del fichero de salida
  • setAudioEncoder(int audio_encoder), setea la codificacion del audio
  • setAudioChannels(int numeroCanales), indicamos la cantidad de canales que vamos a utilizar
  • setAudioEncodingBitRate(int bitRate), a partir del API 8 podemos especificar los bits por segundo (bps) para codificar
  • setMaxDuration(int max_duration_ms), indicamos la duracion maxima para la grabacion
  • setMaxFileSize(long max_filesize_bytes), indicamos el tamaño maximo para el archivo
  • prepare(), prepara la grabacion para la captura de datos y debe ser usado antes de comenzar por medio de start()
  • start(), comienza la captura
  • stop(), finaliza la captura
  • reset(), reinicia el objeto como si acabaramos de crearlo, se debe volver a configurar
  • release(), libera todos los recursos utilizados, sino se ejecuta los mismos seran liberados al destruir el objeto.

Estos son algunos metodos disponibles para la clase MediaRecorder mas orientados al control de audio pero tambien existen algunos para la captura de video, los cuales veremos en otro momento, pasemos a estudiar esta clase por medio de un ejemplo, deben crear un proyecto con las siguientes caracteristicas:

  • Application Name: Grabadora
  • Company name: example.org
  • Minimum SDK API: 9
  • Activity: Empty Activity
  • Activity Name: GrabadoraActivity
  • Layout Name: activity_main

Una vez creada nuestra app, modificaremos el codigo del archivo activity_main.xml por el siguiente:

<?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="match_parent"
android:orientation="horizontal"
>
<Button
android:id="@+id/bGrabar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grabar"
android:onClick="grabar"
/>
<Button
android:id="@+id/bDetener"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Detener Grabacion"
android:onClick="detener"
/>
<Button
android:id="@+id/bReproducir"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reproducir"
android:onClick="reproducir"
/>

</LinearLayout>

Como pueden ver en este layout vamos a agregar tres botones, el primero es para grabar, el segundo para detener la grabacion y el ultimo para reproducir lo grabado, pasemos a modificar el codigo de nuestra clase GrabadoraActivity de la siguiente forma:

package org.example.grabadora;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.io.IOException;

public class GrabadoraActivity extends Activity {

public static final String LOG_TAG = "Grabadora";
private MediaRecorder mediaRecorder;
private MediaPlayer mediaPlayer;
private static final String archivo = Environment.
getExternalStorageDirectory().
getAbsolutePath()+"/audio.3gp";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void grabar(View view){
mediaRecorder = new MediaRecorder();
mediaRecorder.setOutputFile(archivo);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.
OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.
AudioEncoder.AMR_NB);

try{
mediaRecorder.prepare();
}
catch (IOException e){
Log.e(LOG_TAG, "Fallo en la grabacion");
}
mediaRecorder.start();
}

public void detener(View view){
mediaRecorder.stop();
mediaRecorder.release();
}

public void reproducir(View view){
mediaPlayer = new MediaPlayer();
try{
mediaPlayer.setDataSource(archivo);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch (IOException e){
Log.e(LOG_TAG,"Fallo en Reproduccion");
}
}
}

Veamos las primeras cuatro lineas de nuestra clase, la primera sera para crear una constante donde identificaremos a nuestra app en el log para ver si produce alguna falla, luego crearemos los objetos mediaRecorder y mediaPlayer para grabar y reproducir nuestro audio respectivamente y por ultima crearemos una constante para designar el path y el nombre del archivo, el primer metodo se encargara de conseguir la ubicacion de nuestra memoria externa, el segundo la ubicacion absoluta y luego le designaremos un nombre, el metodo onCreate() queda de igual forma a como lo genero el Android Studio, para finalmente tener nuestros metodos para ejecutar con los botones del layout, el primero va a ser grabar(), al cual primero lo crearemos, luego le setearemos el archivo de salida por medio de la constante generada anteriormente (archivo), luego le diremos cual va a ser el medio de ingreso, en este caso el microfono, para luego setear el formato de salida del archivo, en este caso 3gp, para finalmente setear su codificacion, con el archivo configurado pasamos a un bloque try donde en caso de error pasara a notificarlo en el log por medio de un catch, en el bloque try ejecutaremos el metodo prepare() para preparar nuestra grabacion y en caso de no ocurrir ningun error comienza a grabar nuestro archivo, nuestro siguiente metodo sera el de detener(), en este metodo primero detendremos la grabacion y luego por medio de release() liberaremos al objeto y por ende creando nuestro archivo y por ultimo tenemos el metodo reproducir() donde primero crearemos el reproductor luego por medio de un bloque try chequearemos si ocurre un error y lo enviaremos al bloque catch notificando el error, en el bloque try primero le asignaremos a mediaPlayer nuestra grabacion realizada en archivo a traves del metodo setDataSource(), luego lo preparamos por medio de prepare() y por ultimo lo iniciamos por medio de start(), con esto queda concluida nuestra explicacion de los metodos de la clase, si tienen curiosidad Log es una clase utilizada para llevar, como su nombre lo indica, un log que nosotros deseemos almacenar, en este caso seran los errores de grabacion o reproduccion, la clase encargada de controlar esto es android.util.log.
Pasemos a nuestra ultima modificacion para poder probar nuestra app, para ello iremos a nuestra archivo de manifiesto, AndroidManifest.xml, y agregaremos las siguientes lineas:

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name="android.permission.RECORD_AUDIO"
/>

Con estas lineas nuevas le concederemos permiso de lectura de escritura de memoria externa, y tambien nos concedera permisos de lectura, y tambien concederemos permisos de acceso al microfono, con estos dos permisos agregados podremos probar nuestra app pero antes veamos como queda finalmente nuestro archivo de manifiesto:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.grabadora"
>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
>
<activity android:name=".GrabadoraActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission
android:name="android.permission.RECORD_AUDIO"
/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>
</manifest>

Si probamos nuestra app con equipos con version de Android de 5.0 para abajo debera funcionar correctamente, para equipos con Android 6.0 deberan hacer los siguientes pasos pero antes deberan haber instalado la app en el equipo:

  • Ir a configuraciones
  • Ir a Aplicaciones
  • Buscar la app Grabadora y seleccionarla
  • Seleccionar la opcion permisos
  • Habiliten la opcion de Almacenamiento y microfono

Tal como se ve en la siguiente imagen

Con esto podran probar la app sin ningun inconveniente de lo contrario les ocasionara un error, tambien pude probarlo en mi emulador (a pesar de lo que dije al principio) pero para ello deberan hacer una simple modificacion:

  • Corran el emulador
  • A la derecha elijan la opcion de tres puntos (…)
  • En las configuraciones del equipo vayan a Microphone
  • Habiliten las dos disponibles

Deberan quedar como se ve en la siguiente imagen

Con todo esto podran probar tanto en el emulador como en el equipo real sin ningun inconveniente pero si lo probamos notaremos que la app no nos muestra correctamente cuando esta funcionando, para mejorarlo un poco mas vamos a hacer las siguiente modificaciones.
Primero agreguemos las siguientes variables en nuestra clase:

private Button bGrabar, bDetener, bReproducir;

Nota: Puede suceder que a medida que escriban la linea les pida presionar Alt+Enter para agregar el nuevo paquete, Button, en el codigo.

Nuestra siguiente modificacion sera en el metodo onCreate():

bGrabar = (Button) findViewById(R.id.bGrabar);
bDetener = (Button) findViewById(R.id.bDetener);
bReproducir = (Button) findViewById(R.id.bReproducir);
bDetener.setEnabled(false);
bReproducir.setEnabled(false);

Como pueden ver las tres primeras lineas se encargaran de crear los enlaces del codigo Java con respecto a nuestros elementos en el layout, las siguiente lineas deshabilitan los botones de Detener y Reproducir dejandonos solamente la habilidad de grabar, nuestra siguiente modificacion sera en el metodo grabar():

bGrabar.setEnabled(false);
bDetener.setEnabled(true);
bReproducir.setEnabled(false);

La primera linea deshabilitara el boton de Grabar, habilita a Detener y deshabilita a Reproducir, nuestra siguiente modificacion sera en detener():

bGrabar.setEnabled(true);
bDetener.setEnabled(false);
bReproducir.setEnabled(true);

Con estas modificaciones podremos probar nuevamente nuestra app pero ahora veremos como cambia el estado de nuestros botones dependiendo de nuestras acciones pero antes veamos como quedo nuestro codigo final:

package org.example.grabadora;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.io.IOException;

public class GrabadoraActivity extends Activity {

public static final String LOG_TAG = "Grabadora";
private MediaRecorder mediaRecorder;
private MediaPlayer mediaPlayer;
private static final String archivo = Environment.
getExternalStorageDirectory().
getAbsolutePath()+"/audio.3gp";
private Button bGrabar, bDetener, bReproducir;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bGrabar = (Button) findViewById(R.id.bGrabar);
bDetener = (Button) findViewById(R.id.bDetener);
bReproducir = (Button) findViewById(R.id.bReproducir);
bDetener.setEnabled(false);
bReproducir.setEnabled(false);
}

public void grabar(View view){
mediaRecorder = new MediaRecorder();
mediaRecorder.setOutputFile(archivo);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.
OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.
AudioEncoder.AMR_NB);
bGrabar.setEnabled(false);
bDetener.setEnabled(true);
bReproducir.setEnabled(false);

try{
mediaRecorder.prepare();
}
catch (IOException e){
Log.e(LOG_TAG, "Fallo en la grabacion");
}
mediaRecorder.start();
}

public void detener(View view){
bGrabar.setEnabled(true);
bDetener.setEnabled(false);
bReproducir.setEnabled(true);
mediaRecorder.stop();
mediaRecorder.release();
}

public void reproducir(View view){
mediaPlayer = new MediaPlayer();
try{
mediaPlayer.setDataSource(archivo);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch (IOException e){
Log.e(LOG_TAG,"Fallo en Reproduccion");
}
}
}

Si lo probamos debera quedar como el siguiente video

Si lograron lo mismo que se ve en pantalla, felicidades!!! porque hoy hemos hecho algo muy importante e interesante.
En resumen, hoy hemos visto como trabaja la clase MediaRecorder, que metodo podemos utilizar, como utilizarlo en un ejemplo, cuales son los permisos necesarios y como pudimos utilizar una pequeña mejora para un mejor funcionamiento, espero les haya sido util sigueme en Twitter, Facebook o Google+ para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios