IllegalStateException [start called in an invalid state: 1] on restarting Android MediaRecorder

依然范特西╮ 提交于 2019-12-11 03:19:37

问题


I am trying to implement simple logic to start/stop recording with MediaRecorder of Android.

The cycle is

  1. connect to localSocket / set options / mRecorder.prepare();
  2. mRecorder.start();
  3. mRecorder.stop(); mRecorder.reset();

Then, loop between 2 and 3.

In the first cycle, 1,2,3 works fine as intended, however, I've got an error on the second start(restart) after the first stop.

com.example.app E/MediaRecorder﹕ start called in an invalid state: 1

What is the MediaRecorder state 1? What do I miss? Thanks for your input.

if (cmd.equals("connect"))
{
    try
    {
        sender.connect(new LocalSocketAddress(SOCKET_ADDRESS)); 
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mRecorder.setOutputFile(sender.getFileDescriptor()); 
        mRecorder.prepare(); 
    }
    catch (IOException e)
    {   e.printStackTrace();  } 
} 
if (cmd.equals("start"))
{
    try
    { 
        mRecorder.start(); 
    }
    catch (IllegalStateException e)
    { e.printStackTrace();  } 
} 
if (cmd.equals("stop"))
{ 
    try
    {
        mRecorder.stop();
        mRecorder.reset(); 
    }
    catch (Exception e)
    { e.printStackTrace(); }
}

回答1:


I'd had the same problem. I had to make a function initRecorder that sets up and prepares the media recorder. Then I called this function each time after the start button was pressed but before start was called. recreate() after stop also works.

    StartRecording.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 100);

            try {
                try {
                    initRecorder(mHolder.getSurface());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mMediaRecorder.start();

                Log.e("mRecorder", "Started");
            } catch (RuntimeException e) {
                Log.e("mRecorder", "Start Failure");
                e.printStackTrace();

            }
        }
    });


private void initRecorder(Surface surface) throws IOException {

    toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 1000);

    if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();

   // mMediaRecorder.setCamera(mCamera);

    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    //       mMediaRecorder.setOutputFormat(8);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
    //mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
    mMediaRecorder.setVideoFrameRate(30);
   // mMediaRecorder.setVideoSize(640,480);

    mMediaRecorder.setPreviewDisplay(surface);
    mMediaRecorder.setOutputFile(path);

  // mMediaRecorder.setPreviewDisplay(mHolder.getSurface());
    mMediaRecorder.setMaxDuration(10000); // 10 seconds
    try {
        mMediaRecorder.prepare();
        Log.e("mRecorder", "Prepared");
    } catch (IOException e) {
       Log.e("mRecorder", "Prepare Failure");
        e.printStackTrace();
    }

    mInitSuccesful = true;

}



回答2:


In the scond cycle you have not called prepare, you need to call that before you can call start on media recorder




回答3:


This is a self-answer, but I would not check as the answer because it's just work-around.

According to @Pulkit Sethi, state-1 means either MediaRecorder does not start properly or stop properly.

Perhaps, it's due to the local socket object sender.getFileDescriptor() as the target of setOutputFile.

So far, it's way too complicated and I could not find a way to stop gracefully enough to re-start or re-use MediaRecorder, I chose to dispose all everytime.

So The cycle is

  1. start localSocket/Server
  2. connect to localSocket / set options / mRecorder.prepare();
  3. mRecorder.start();
  4. stop/close/release whole

This looks not the smartest way, but at least simple and stable, and I am happy with the result to start/stop/ & re-start as intended.

   if (cmd.equals("stop"))

    try
    {
        if (sender != null)
        {
            sender.close();
        }
        if (receiver != null)
        {
            receiver.close();
        }
        if (server != null)
        {
            server.close();
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();  
    } 
    sender = null;
    receiver = null;
    server = null;  
}

for MediaRecorder

mRecorder.release();




回答4:


The output file needs to be an actual file, not a socket. This is because MediaRecorder usually needs to be able to seek back in the file to update the header when the recording ends, and you can't seek in a socket.



来源:https://stackoverflow.com/questions/21396140/illegalstateexception-start-called-in-an-invalid-state-1-on-restarting-androi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!