Search code examples
androidillegalstateexceptionmediarecorder

IllegalStateException while starting Media recorder


I got a problem in getting amplitude in my app.

My start method

public void start() {
    if (mRecorder == null) {
        try {
            mRecorder = new MediaRecorder();

            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
            mRecorder.setOutputFile("/dev/null");
            try {
                mRecorder.prepare();
                mRecorder.start();
            } catch (IOException e) {
                e.printStackTrace();
                    mRecorder = null;
            } catch(IllegalStateException e ){
                e.printStackTrace();
                mRecorder = null;
            }

        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }
}

And my stop method:

public void stop() {
    if (mRecorder != null) {
        try {
            mRecorder.stop();
        } catch (RuntimeException stopException) {
            //handle cleanup here
        } finally {
            mRecorder.release();
        }
        mRecorder = null;
    }
}

It throws IllegalStateException on

mRecorder.start();

I tried different OutputFormats and AudioEncoders but none of them was working. :/ Also tried it on different phones.

This is my stacktrace.

W/MediaRecorder: mediarecorder went away with unhandled events
E/MediaRecorder: start failed: -38
W/System.err: java.lang.IllegalStateException
W/System.err:     at android.media.MediaRecorder.start(Native Method)
W/System.err:     at com.oscarsenior.oscar.util.sensorHelpers.SoundMeter.start(SoundMeter.java:33)
W/System.err:     at com.oscarsenior.oscar.util.service.SensorService.updateAmplitude(SensorService.java:616)
W/System.err:     at com.oscarsenior.oscar.util.service.SensorService$6.onSensorChanged(SensorService.java:606)

I run this every 15 minutes for 3 seconds to measure max amplitude.


Solution

  • I finally find the solution to my problem.

    The problem was lying in my service. I was using MediaRecorder twice at the same time using same MediaRecorder.AudioSource.

    The solution for this is to use the same mRecorder for both cases.

    So I created Singleton from my SoundMeter class.

    protected SoundMeter(){
    
    }
    
    public static SoundMeter getInstance(){
        if(instance == null){
            instance = new SoundMeter();
        }
        if(!instance.isRecording || instance.mRecorder == null){
            instance.start();
        }
        return instance;
    }
    

    So I get instance of SoundMeter and if the instance with mRecorder is not initialized, I will use same SoundMeter.start() method as in question.

    I added mRecorder.reset() to stop() method, so release mRecorder will clear its state. Probably I could release MediaRecorder once finished not every time I stop listening for a while, but I rather free some memory on background when I do not need it.

    if (mRecorder != null) {
        try {
            mRecorder.stop();
        } catch (RuntimeException stopException) {
            //handle cleanup here
        } finally {
            mRecorder.reset();
            mRecorder.release();
        }
        mRecorder = null;
        isRecording = false;
    }