问题
I am trying to implement simple logic to start/stop recording with MediaRecorder
of Android.
The cycle is
- connect to localSocket / set options / mRecorder.prepare();
- mRecorder.start();
- 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
- start localSocket/Server
- connect to localSocket / set options / mRecorder.prepare();
- mRecorder.start();
- 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