My app tries to record the sound by using the MediaRecorder API. My start recording method looks like this:
public void start() {
if(this.mRecorder == null) {
try{
this.mRecorder = new MediaRecorder();
this.mRecorder.setAudioSource(1);
this.mRecorder.setOutputFormat(1);
this.mRecorder.setAudioEncoder(1);
this.mRecorder.setOutputFile("/dev/null");
} catch (RuntimeException re) {
}
try {
this.mRecorder.prepare();
} catch (IllegalStateException var3) {
var3.printStackTrace();
} catch (IOException var4) {
var4.printStackTrace();
}
this.mRecorder.start();
this.mEMA = 0.0D;
}
}
But I get crash reports from users on the following line:
this.mRecorder.start();
The IllegalStateException stack trace is:
java.lang.RuntimeException:
atandroid.app.ActivityThread.performResumeActivity(ActivityThread.java:3493)
atandroid.app.ActivityThread.handleResumeActivity(ActivityThread.java:3533)
atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2791)
atandroid.app.ActivityThread.-wrap12(ActivityThread.java)
atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1532)
atandroid.os.Handler.dispatchMessage(Handler.java:102)
atandroid.os.Looper.loop(Looper.java:163)
atandroid.app.ActivityThread.main(ActivityThread.java:6342)
atjava.lang.reflect.Method.invoke(NativeMethod)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
atcom.android.internal.os.ZygoteInit.mai(ZygoteInit.java:770)
Causedby:java.lang.IllegalStateException:
atandroid.media.MediaRecorder.start(NativeMethod)
atmeasure.sound.decibels.SoundMeter.start(SoundMeter.java:43)
atmeasure.sound.decibels.MyActivity.start(MyActivity.java:138)
atmeasure.sound.decibels.MyActivity.onResume(MyActivity.java:521)
atandroid.app.Instrumentation.callActivityOnResume(Instrumentation.java:1270)
atandroid.app.Activity.performResume(Activity.java:6960)
atandroid.app.ActivityThread.performResumeActivity(ActivityThread.java:3470)
The app is crashing for users. Any help!
Related
This is my code snippet.
private fun record() {
recorder.setAudioSource(MediaRecorder.AudioSource.MIC)
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
val path: File = filesDir
try {
tempFile = File.createTempFile("audioTemp", ".3gp", path)
} catch (e: IOException) {
Log.d("recording error", "recording error:", e)
} catch (e: FileAlreadyExistsException) {
Log.d("File already Exist", e.toString())
}
recorder.setOutputFile(tempFile?.absolutePath)
try {
recorder.prepare()
} catch (e: IOException) {
Log.d("recording error", "recording error:", e)
}
recorder.start()
}
private fun stopRecord() {
recorder.stop()
recorder.release()
button_play_sample.isEnabled = true
button_record.isEnabled = true
player.setOnCompletionListener(this)
try {
player.setDataSource(tempFile?.absolutePath)
} catch (e: IOException) {
Log.d("stop recording error", "Stop Recording Error:", e)
}
try {
player.prepare()
} catch (e: IOException) {
Log.d("recording error", "recording error:", e)
}
}
private fun play() {
player.start()
button_record.isEnabled = false
}
override fun onCompletion(mp: MediaPlayer?) {
handler = Handler()
handler?.postDelayed({button_record.isEnabled = true}, 1000)
}
I cant figure out why but I have a record button that records audio. When the activity first loads, the recording loads. When I press it the second time because I don't like my first recording, instead of overwriting the old file and setting up record again, App crashes instead.
In the Android Developer Guide, it says
When you are done with the MediaRecorder instance free its resources
as soon as possible by calling release().
see this sample code from the Developer site:
private void stopRecording() {
recorder.stop();
recorder.release();
recorder = null;
}
Your code snippet doesn't check if recorder is being used. You might want to do that before using the MediaRecorder object again.
private fun record() {
if (recording) {
stopRecording()
}
// do recording snippet here...
}
I have activity with SurfaceView, i want start and stop video record in this Activity, but i want continue record video if i go to other Activity. Now i start record video(in activity 1) and go to other Activity, when i back (to activity 1) and want stop record video, my app is freezes when called recorder.stop(); How i can fix it?
Init SurfaceView and SurfaceHolder:
SurfaceView cameraView = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = cameraView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Start record video:
protected void startRecordVideo() {
if (cam == null) {
cam = Camera.open();
try {
cam.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
recording = true;
recorder = new MediaRecorder();
recorder.setCamera(cam);
initRecorder();
prepareRecorder();
try {
cam.unlock();
} catch (RuntimeException e) {
e.printStackTrace();
}
recorder.start();
}
Stop record video (this is app freezes):
protected void stopRecordVideo() { //cam - Camera, recorder - MediaRecorder
mc.IS_RECORD = false;
recording = false;
try {
cam.lock();
recorder.stop(); //app freezes in this line (i used Log)
recorder = null;
cam.reconnect();
cam.release();
cam = null;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
P.S. i do not use camera.startPreview(); and camera.stopPreview();
Try to wrap stopRecordVideo inside a Thread, so it doesnt block the main (UI) Thread.
If it doesnt work, take a look at this question :
Android Media Recording using threads
It seems you must do a little "hack"
I'm trying to write a function that will record the users voice while an instrumental is playing in the background.
I have been fairly successful in getting 2 MediaPlayers to start at almost the exact same time. Using Threads and the CyclicBarrier, I have been able to start 2 MediaPlayer within 5 milliseconds of each, which sounds pretty good.
The problem is that whenever I attempt to start a MediaRecorder and a MediaPlayer at the same time, there is a noticeable delay between them. This is problematic, because when I playback the recorded audio and the instrumental, they are not in sync with each other because the recorded started at a different time than the player.
Here is the function and the 2 Threads that I'm trying to use for the Recorder and Player. I apologize for the length, but if anybody has any better ideas I would be very grateful:
private void onRecord(boolean start) {
if (start) {
final CyclicBarrier recordBarrier = new CyclicBarrier(2);
final CyclicBarrier postrecordBarrier = new CyclicBarrier(2);
Thread beatTask = new Thread(new RecordBeatPlayTask(recordBarrier, postrecordBarrier), "Thread 1");
Thread recordTask = new Thread(new RecordVoiceRecordTask(recordBarrier, postrecordBarrier), "Thread 2");
beatTask.start();
recordTask.start();
}
else {
mRecorder.stop();
mRecordBeatPlayer.stop();
mRecorder.release();
mRecorder = null;
mRecordBeatPlayer.release();
mRecordBeatPlayer = null;
}
}
private static class RecordVoiceRecordTask implements Runnable {
private CyclicBarrier barrier;
private CyclicBarrier barrier2;
public RecordVoiceRecordTask(CyclicBarrier barrier, CyclicBarrier barrier2) {
this.barrier = barrier;
this.barrier2 = barrier2;
}
public void run() {
try {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
mRecorderPath += "/HypeHopRecording.mp4";
mRecorder.setOutputFile(mRecorderPath);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e("Recorder failed", "prepare() failed");
}
barrier.await();
mRecorder.start();
barrier2.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private static class RecordBeatPlayTask implements Runnable {
private CyclicBarrier barrier;
private CyclicBarrier barrier2;
public RecordBeatPlayTask(CyclicBarrier barrier, CyclicBarrier barrier2) {
this.barrier = barrier;
this.barrier2 = barrier2;
}
public void run() {
try {
mRecordBeatPlayer = new MediaPlayer();
try {
mRecordBeatPlayer.setDataSource(mBeatPath);
mRecordBeatPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
barrier.await();
mRecordBeatPlayer.start();
barrier2.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
basically, there is deplay between 'mRecordBeatPlayer.start()' and user can hear the sound, you have to test out this deplay.
While I use almost the same code to play two videos, the first works perfectly, but the second does not. When I press the next video button, the program crashed with:
WARN/System.err(15726): java.lang.IllegalStateException
WARN/System.err(15726): at android.media.MediaPlayer.setDataSource(Native Method)
Source code:
the first play code:
mediaPlayer = new MediaPlayer();
playURI = receiveIntent.getStringExtra("playURI");
showDebugInfo("play uri "+playURI);
Log.e("Gplayer on create", "play uri "+playURI);
try {
mediaPlayer.setDataSource(playURI);
} catch (IllegalArgumentException e) {
Log.v(LOGTAG, e.getMessage());
finish();
} catch (IllegalStateException e) {
Log.v(LOGTAG, e.getMessage());
finish();
} catch (IOException e) {
Log.v(LOGTAG, e.getMessage());
finish();
}
when press next button it runs the following code:
String uri = listAdapter.getItem(position).getItem().getFirstResource().getValue();
showDebugInfo(" Uri "+uri);
if(mediaPlayer != null){
mediaPlayer.stop();
}
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(uri);
mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
finish();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
finish();
}
Why does this happen? and I check the two parts only the different that, the first one is new a mediaplayer and the second is let the mediaplayer stop and reset then the same.
I had the same problem.
You need to call mediaPlayer.reset(); before you are calling in the second video mediaPlayer.setDataSource(uri); the reason is, because the function mediaPlayer.setDataSource(uri); can be called only on idle state, and mediaPlayer.reset(); is the function that take you to idle state.
I understand it from this answer, even though the question is a bit different.
This is my method in service for playing files, on AVD everything works fine, no errors, when I click the control on PDA I get these LogCat events: http://pastebay.com/125483. I have no clue what is happening. Please advise.
public void playAudio (int playAudio) {
player = MediaPlayer.create(this, playAudio);
try {
if (player != null) {
player.stop();
}
player.prepare();
player.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
I solved it, the problem was I called prepare(); after MediaPlayer.create since it prepares the MediaPlayer already.