为什么停止MediaRecorder时会收到IllegalStateException? [英] Why am I getting an IllegalStateException when stopping MediaRecorder?

查看:159
本文介绍了为什么停止MediaRecorder时会收到IllegalStateException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了更好地理解Android中的音频录制和播放,我在android开发教程

因此,为了确保我们应该为

为了安全地停止或释放记录器相关资源,我们必须确保记录器已被注视.

  recorder.start();//现在开始记录 

输入您的特定代码

  boolean isRecording = false;私人无效startRecording(){记录器=新的MediaRecorder();records.setAudioSource(MediaRecorder.AudioSource.MIC);records.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);records.setOutputFile(fileName);System.out.println(fileName);records.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);尝试 {records.prepare();records.start();isRecording = true;} catch(IOException e){Log.e(LOG_TAG,"prepare()失败"));//e.printStackTrace();}}....私人无效stopRecording(){if(isRecording){records.stop();}records.reset();//您可以通过返回setAudioSource()步骤来重用该对象records.release();//现在无法重用该对象isRecording = false;} 

如果我们处于录制状态,请停止它,然后释放它,否则就释放它.

To get a better understanding of audio recording and playback in Android, I've implemented a clone of the code in the android dev tutorial https://developer.android.com/guide/topics/media/mediarecorder#sample-code

No errors occur upon starting the recording, however, I have yet to verify if any recording is actually taking place. Then when I stop recording, the app crashes to the previous activity and on a subsequent attempt the "app keeps crashing" dialog pops up and the app exits.

I have <uses-permission android:name="android.permission.RECORD_AUDIO" /> in the AndroidManifest

private void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();   // Line 53 //
        }
    }

private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
    }

private void stopRecording() {
        recorder.stop();       // Line 98 //
        recorder.release();
        recorder = null;
    }

class RecordButton extends AppCompatButton {
        boolean mStartRecording = true;

        OnClickListener clicker = new OnClickListener() {
            public void onClick(View v) {
                onRecord(mStartRecording);
                if(mStartRecording) {
                    setText(R.string.stop_recording);
                } else {
                    setText(R.string.start_recording);
                }
                mStartRecording = !mStartRecording;
            }
        };

        public RecordButton(Context ctx){
            super(ctx);
            setText(R.string.start_recording);
            setOnClickListener(clicker);
        }
    }

Logcat output:

2020-02-14 10:57:09.789 23619-23619/? E/Zygote: accessInfo : 1
2020-02-14 10:57:09.820 23619-23619/? E/.xxxxxx.xxxxxx: Unknown bits set in runtime_flags: 0x8000
2020-02-14 10:57:12.925 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/MediaRecorder: stop called in an invalid state: 8
2020-02-14 10:57:12.927 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: xx.xxxxxxx.xxxxxx.xxxxxxx, PID: 23619
    java.lang.IllegalStateException
        at android.media.MediaRecorder._stop(Native Method)
        at android.media.MediaRecorder.stop(MediaRecorder.java:1440)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.stopRecording(RecordActivity.java:98)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.onRecord(RecordActivity.java:53)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.access$000(RecordActivity.java:21)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity$RecordButton$1.onClick(RecordActivity.java:108)
        at android.view.View.performClick(View.java:7866)
        at android.widget.TextView.performClick(TextView.java:14952)
        at android.view.View.performClickInternal(View.java:7839)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29363)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7811)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)

I can provide any relevant additional code or details if needed

EDIT Permission is requested with the following:

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case REQUEST_RECORD_AUDIO_PERMISSION:
                permissionToRecordAccepted  = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                break;
        }
        if (!permissionToRecordAccepted ) finish();

    }

and inside onCreate():

ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);

EDIT 2 * I've verified that the audio recording file is being created but is 0 B in size

解决方案

Media Player

in the below flowchart, stop() valid states are {Prepared, Started, Stopped, Paused, PlaybackCompleted}. other states(Idle,Initialized,Error) are NOT valid states in order to call stop(). otherwise, IllegalStateException thrown.

Therefore, for Ensure we should set states listeners for the MediaPlayer. Because, Prepared state is initialized earlier then by setOnPreparedListener for player we can safely stop player.

...
boolean isPrepared = false;
...
recorder.setOnPreparedListener ....
{
...
isPrepared = true;
...
}
...
private void stopRecording() {
    if(isPrepared){
        player.stop();  
        ...
    }
}

i made the code summarized for better understanding.

Media Recorder

in the below flowchart, stop() is available only if you are in recording state. otherwise, calling stop() throws IllegalStateException.

in order to safely stop or release recorder related resources we have to make sure recorder has been stared.

recorder.start();   // Recording is now started 

for your specific code

boolean isRecording = false;
private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
            recorder.start();
            isRecording = true;
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
}
....
private void stopRecording() {
    if(isRecording){
        recorder.stop();  
    }
    recorder.reset();   // You can reuse the object by going back to setAudioSource() step
    recorder.release(); // Now the object cannot be reused
    isRecording = false;
}

if we are in recording state stop it then release it otherwise just release it.

这篇关于为什么停止MediaRecorder时会收到IllegalStateException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆