启动媒体录制器时出现IllegalStateException

时间:2018-01-08 09:03:55

标签: android illegalstateexception mediarecorder

我在应用程序中获得振幅时遇到了问题。

我的开始方法

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();
        }
    }
}

我的停止方法:

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

它会在

上抛出 IllegalStateException
mRecorder.start();

我尝试了不同的OutputFormats和AudioEncoders但它们都没有工作。 :/也在不同的手机上试过。

这是我的堆栈跟踪。

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)

我每隔15分钟运行一次,持续3秒钟,以测量最大振幅。

2 个答案:

答案 0 :(得分:0)

首先允许权限

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

然后启动()方法

MediaRecorder mRecorder;
File file;

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

            file = new File(Environment.getExternalStorageDirectory() + "/Demo");
            if (!file.exists())
                file.mkdir();
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mRecorder.setOutputFile(file.getAbsoluteFile() + "/demoAudio.mp3");
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

            //mRecorder.setOutputFile();
            try {
                mRecorder.prepare();
                mRecorder.start();
            } catch (IOException e) {
                e.printStackTrace();
                mRecorder = null;
            } catch (IllegalStateException e) {
                e.printStackTrace();
                mRecorder = null;
            }

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

然后停止()方法

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

并且使用此方法在应用程序处于Backgroud时停止录制

@Override
protected void onStop() {
    super.onStop();
    stop();
}

答案 1 :(得分:0)

我终于找到了解决问题的方法。

问题在于我的服务。我使用相同的 MediaRecorder.AudioSource 同时使用MediaRecorder两次。

对此解决方案是对两种情况使用相同的 mRecorder

所以我从 SoundMeter 类创建了 Singleton

protected SoundMeter(){

}

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

所以我得到 SoundMeter 的实例,如果没有初始化 mRecorder 的实例,我将使用相同的 SoundMeter.start()方法如此问题。

我将 mRecorder.reset()添加到 stop()方法,因此发布 mRecorder 将清除其状态。可能我可以在每次停止听一段时间后发布 MediaRecorder ,但是当我不需要时,我宁愿在后台释放一些内存。

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