2011-01-30 13 views
49

En el código siguiente, mi objeto audioRecord no se está inicializando. Intenté moverlo al método onCreate y lo hice global. He registrado el estado y eso devuelve un valor de 1, lo que significa que está listo para usar. El depurador dice que se está llamando al startRecording en un objeto no inicializado. También dice que no pudo obtener la fuente de audio.Objeto AudioRecord que no se inicializa

¿Por qué me salen estos errores?

package com.tecmark; 

    import java.io.BufferedOutputStream; 
    import java.io.DataOutputStream; 
    import java.io.File; 
    import java.io.FileOutputStream; 
    import android.app.Activity; 
    import android.media.AudioFormat; 
    import android.media.AudioRecord; 
    import android.media.MediaRecorder; 
    import android.os.Bundle; 
    import android.os.Environment; 
    import android.util.Log; 
    import android.view.View; 
    import android.widget.TextView; 

    public class recorder extends Activity { 

     private Thread thread; 
     private boolean isRecording; 
     private AudioRecord recorder; 
     private FileOutputStream os; 
     private BufferedOutputStream bos; 
     private DataOutputStream dos; 
     private TextView text; 
     private int audioSource = MediaRecorder.AudioSource.MIC; 
     private int sampleRate = 22050; 
     private int channel = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
     private int encoding = AudioFormat.ENCODING_PCM_16BIT; 
     private int result = 0; 
     private int bufferSize; 
     private byte[] buffer; 

     /** Called when the activity is first created. */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.main); 

      Log.v("onCreate", "layout set, about to init audiorec obj"); 
      text = (TextView)findViewById(R.id.TextView01); 

      bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding); 
      buffer = new byte[bufferSize]; 

      recorder = new AudioRecord(audioSource, sampleRate,channel,encoding, 
        AudioRecord.getMinBufferSize(sampleRate, channel,encoding)); 
      Log.i("recorder obj state",""+recorder.getRecordingState()); 
     } 

     public void onClickPlay(View v){ 

     } 


     public void record(){ 
      Log.i("inside record method", "******"); 
     File path = Environment.getExternalStorageDirectory(); 
      Log.v("file path", ""+path.getAbsolutePath()); 

      File file = new File(path, "test.wav"); 

      if(file.exists()){ 
      file.delete(); 
      } 

      path.mkdirs(); 
      Log.v("file path", ""+file.getAbsolutePath()); 

      try { 
      os = new FileOutputStream(file); 
      bos = new BufferedOutputStream(os);    
       dos = new DataOutputStream(bos);   
      } catch (Exception e1) { 
      e1.printStackTrace(); 
      } 

      int bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding); 
      byte[] buffer = new byte[bufferSize]; 
      recorder.startRecording(); 
      isRecording = true; 
      try{ 
       while (isRecording){ 
      result = recorder.read(buffer, 0, bufferSize); 
      for(int a=0; a<result;a++){ 
       dos.write(buffer[a]); 

       if(!isRecording){ 
        recorder.stop();   
        break; 
       } 

      } 

      } 
      dos.flush(); 
      dos.close(); 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

    }// end of record method 

    public void onClickStop(View v){ 
     Log.v("onClickStop", "stop clicked"); 
     isRecording=false; 
    } 
    public void onClickReverse(View v){ 
     Log.v("onClickReverse", "reverse clicked"); 
    } 
    public void onClickRecord(View v){ 
     Log.v("onClickRecourd", "record clicked, thread gona start"); 
     text.setText("recording"); 
     thread = new Thread(new Runnable() { 
      public void run() { 
       isRecording = true; 
       record(); 
      } 
     }); 

     thread.start(); 
     isRecording = false; 
    } 
}//end of class 

Logcat

01-30 15:23:16.724: ERROR/AudioRecord(12817): Could not get audio input for record source 1 01-30 15:23:16.729: 
ERROR/AudioRecord-JNI(12817): Error creating AudioRecord instance: initialization check failed. 01-30 15:23:16.729: 
ERROR/AudioRecord-Java(12817): [ android.media.AudioRecord ] Error code 
-20 when initializing native AudioRecord object. 01-30 15:23:16.729: INFO/recorder obj state(12817): 1 01-30 15:23:16.729: 
WARN/dalvikvm(12817): threadid=13: thread exiting with uncaught exception (group=0x4001b180) 01-30 15:23:16.729: 
ERROR/AndroidRuntime(12817): Uncaught handler: thread Thread-7 exiting due to uncaught exception 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):  at android.media.AudioRecord.startRecording(AudioRecord.java:495) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):  at com.tecmark.recorder.record(recorder.java:114) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):  at com.tecmark.recorder$1.run(recorder.java:175) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):  at java.lang.Thread.run(Thread.java:1096) 
+0

use recorder.getState() para obtener el estado correcto – Tom

+0

Después de reiniciar mi dispositivo (que el micrófono no está funcionando después de intentar una configuración de inicialización incorrecta, para comprobar si se ha ingresado o no, probando con micrófono será fácil), luego probé el método de inicialización try-all-the-combination ¡y funciona! gracias! – WTing

Respuesta

83

El truco con el uso de AudioRecord es que cada dispositivo puede tener diferentes configuraciones de inicialización, por lo que tendrá que crear un método que se repite sobre todas las posibles combinaciones de velocidades de bits, codificación, etc.

private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 }; 
public AudioRecord findAudioRecord() { 
    for (int rate : mSampleRates) { 
     for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) { 
      for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) { 
       try { 
        Log.d(C.TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " 
          + channelConfig); 
        int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat); 

        if (bufferSize != AudioRecord.ERROR_BAD_VALUE) { 
         // check if we can instantiate and have a success 
         AudioRecord recorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize); 

         if (recorder.getState() == AudioRecord.STATE_INITIALIZED) 
          return recorder; 
        } 
       } catch (Exception e) { 
        Log.e(C.TAG, rate + "Exception, keep trying.",e); 
       } 
      } 
     } 
    } 
    return null; 
} 

AudioRecord recorder = findAudioRecord(); 
recorder.release(); 
+3

^^^ esto. Tuve que rastrear el código fuente de Android para resolver esto yo mismo. – Vagrant

+0

sigue diciendo que lo mismo para mí no funciona –

+6

Esto no funcionará tan bien como piensas porque algunos dispositivos Android entrarán en un agujero negro del infierno si usas una frecuencia de muestreo no compatible. La única forma de que el micrófono vuelva a funcionar es reiniciar el dispositivo. –

1

he notado que cuando la tarjeta SD en la avd me postulo se llena el constructo AudioRecord r devuelve nulo. ¿Has intentado borrar la tarjeta SD?

+0

gracias ... amigo ... después de borrar la tarjeta SD ... mi problema se resolvió –

9

De acuerdo con los javadocs, todos los dispositivos están garantizados para soportar este formato (para la grabación):

44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT.

Cambie a CHANNEL_OUT_MONO para la reproducción.

+7

Sí, pero muchos dispositivos realmente no. –

+3

Sí, los documentos están equivocados en esto. Los teléfonos de gama baja tienden a no admitir esto. –

+0

¿Sigue siendo cierto o es un estándar? – Jeremy

85

que tenían el mismo problema, se resuelve poniendo

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

en el manifiesto.

Desde Lollipop, también debe pedirle específicamente al usuario cada permiso. Como pueden haberlos revocado. Asegúrate de que el permiso sea otorgado.

+5

solo una nota para los recién llegados, en Android 6 Marshmallow, también tengo que habilitar manualmente el permiso para la aplicación: https://www.howtogeek.com/230683/how-to-manage-app-permissions-on-android- 6.0/ –

2

Acabo de tener el mismo problema. La solución fue reiniciar el dispositivo. Mientras jugaba con el código, no solté el objeto AudioRecord, que obviamente causó que el dispositivo de audio se quedara atascado. Para probar si el dispositivo de audio funcionaba o no, descargué Audalyzer de Google Play.

+0

Esto funcionó para mí también. Sabía que tenía que ser el dispositivo y no el código porque no cambié nada entre una versión en funcionamiento y otra que no funcionaba. ¡Gracias! – CodyMace

0

Creo que esto tiene que ver con el hilo sin saber que ha pausado la principal actividad y aún tratando de grabar después de haber detenido la grabadora.

Lo resolví cambiando mis métodos onResume() y onPause() para modificar el booleano isRecording.

public void onResume() { 
    ... 
    isRecording = true; 
} 

public void onPause() { 
    ... 
    isRecording = false; 
} 

Luego, en su hilo, rodean tanto a su startRecording() y stop() con sentencias if cheques para isRecording:

if(isRecording) 
    recorder.startRecording(); 
... 
if(isRecording) 
    recorder.stop(); // which you've done 
0

Reescribí la respuesta de @DustinB para cualquier persona que está utilizando Xamarin Android AudioRecord con C# .

int[] sampleRates = new int[] { 44100, 22050, 11025, 8000 }; 
Encoding[] encodings = new Encoding[] { Encoding.Pcm8bit, Encoding.Pcm16bit }; 
ChannelIn[] channelConfigs = new ChannelIn[]{ ChannelIn.Mono, ChannelIn.Stereo }; 

//Not all of the formats are supported on each device 
foreach (int sampleRate in sampleRates) 
{ 
    foreach (Encoding encoding in encodings) 
    { 
     foreach (ChannelIn channelConfig in channelConfigs) 
     { 
      try 
      { 
       Console.WriteLine("Attempting rate " + sampleRate + "Hz, bits: " + encoding + ", channel: " + channelConfig); 
       int bufferSize = AudioRecord.GetMinBufferSize(sampleRate, channelConfig, encoding); 

       if (bufferSize > 0) 
       { 
        // check if we can instantiate and have a success 
        AudioRecord recorder = new AudioRecord(AudioSource.Mic, sampleRate, channelConfig, encoding, bufferSize); 

        if (recorder.State == State.Initialized) 
        { 
         mBufferSize = bufferSize; 
         mSampleRate = sampleRate; 
         mChannelConfig = channelConfig; 
         mEncoding = encoding; 
         recorder.Release(); 
         recorder = null; 
         return true; 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(sampleRate + "Exception, keep trying." + ex.Message); 
      } 
     } 
    } 
} 
4

Ahora, con lollipop, debe solicitar específicamente al usuario cada permiso. Asegúrate de que el permiso sea otorgado.

3

Incluso después de hacer todos los pasos anteriores que estaba recibiendo el mismo problema, lo que funcionó para yo era que mi os era malvavisco y tuve que pedir los permisos.

+0

Mente compartiendo los permisos que funcionaron para usted (casi un año después ...) Estoy usando RECORD_AUDIO y MODIFY_AUDIO_SETTINGS – darkpbj

1

en mi caso tuve que permitir manualmente el permiso en android 7 para micrófono, como comentó sean zhu.

Cuestiones relacionadas