How to use the same recorder object repeatedly - android

I am creating a MediaRecorder and using it to generate a video clip. It works perfectly the first time. I end the video shooting process by setting the maximum file size to 5MB, after which it enters the onInfo method and the completely that particular video snap.
Now I want to generate 5 such clips, one after the other. For which I add the following to the onInfo method:
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
// TODO Auto-generated method stub
//System.out.println("Reached onInfoListener");
if(what==android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)
{
Toast.makeText(getApplicationContext(), "Video clip "+video_count+" recorded", Toast.LENGTH_SHORT).show();
recorder.stop(); //recorder is an object of type MediaRecorder
recorder.reset();
initRecorder(); //Reinitializing for subsequent video generation
prepareRecorder(); //Re preparing for subsequent video generation
}
}
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"/FOLDERNAME");
if(!dir.exists())
{
dir.mkdir();
}
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
recorder.setOutputFile("/sdcard/FOLDERNAME/video"+video_count+".mp4");
recorder.setMaxDuration(50000); // 50 seconds
recorder.setMaxFileSize(5*1048576); // Approximately 5 megabytes
}
private void prepareRecorder() {
recorder.setPreviewDisplay(cameraView.getHolder().getSurface());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
NOTE: videocount is a variable used to give a distinct name to each generated video clip.
However after successfully capturing the first video clip, and just before the second clip an start recording, a IllegalStateException is encountered when I try to start the recorder object again. Since I am using recorder.reset() API, I thought that I would be able to reuse the recorder object for subsequent iterations. But it is giving this problem.
How to solve this issue? Is it neccessary to provide some delay after reinitializing the recorder object?
EDIT: If I keep the recorder.start() inside a button click, this works, that is, on every button click, a separate video is taken. But if I ask it to take say, 5 videos, on a single button click, the app crashes before it starts taking the second video, that is, it works only once. How to overcome this non-uniformity?

Going by the official documentation you need to call the setOutputFormat() method before you can call prepare(), like this:
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

Related

Android: Record and play video in the same SurfaceView

I want to see the video that I'm currently recording in a SurfaceView and if the recodring finished I wanto to replay the video in the same SurfaceView.
Even though I thought it would be a common feature in Apps, I couldn't find any example and couldn't make my code work.
private void prepareRecorder() {
try {
recorder = new MediaRecorder();
recorder.setPreviewDisplay(holder.getSurface());
camera.unlock();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
recorder.setProfile(camcorderProfile);
File newFile = new File(videoFilePath);
recorder.setOutputFile(newFile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}catch(Exception e){
releaseCamera();
}
}
//
public void onClick(View v) {
if(mediaPlayer!=null) {
mediaPlayer.reset();
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(videoFile.getAbsolutePath());
SurfaceView surfaceView = (SurfaceView) getView().findViewById(R.id.videoInvitationFragSurfaceView);
mediaPlayer.setSurface(surfaceView.getHolder().getSurface());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
If I just record the video my code works, if just play the video it works as well. Any ideas?
Thanks in advance
Edit: As a current workaround I use two SurfaceViews and "hide" them (set size to 0) if needed
If I just record the video my code works, if just play the video it works as well. Any ideas?
As much I understand, you can reuse same surface view only after it is destroyed and regenerated, i.e you can reuse same SurfaceView only after surfaceDestroyed() is called and then surfaceCreated() is called only after this destroy and create cycle you can reuse SurfaceView.
To achive this all you have to do is: after video recording is done set SurfaceView visibility to GONE which will ensure surfaceDestroyed() call back and again set SurfaceView visibility to VISIBLE which will call surfaceCreated() after that start video playback.
This is very cumbersome process so I used same SurfaceView for recording and playback in following way:
when Activity is created check if VideoFile is available in Intent
if yes use SurfaceView for playback
now if user deletes video restart activity
As VideoFile is not found in intent use SurfaceView for recording
Once recording is done and user want to playback video restart
Activity with VideoFile information attached in Intent

How to record audio on Android without crash?

I'm developing on a Nitro HD with Gingerbread. I want to record audio and I experience an infinite hang while calling MediaRecorder.stop().
I know that my phone can record sound because I have an application that does it exactly.
I read the book "Android for programmers" from Deitel et al. and there is the example VoiceRecorder in chapter 16. Everything seems fine but the app hangs forever when it calls MediaRecorder.stop(). Also, the resource is not released and I have to reboot the phone to release it.
Here is the part of the code where the calls are done (see Deitel et al., "Android for Programmers", Prentice Hall, 2012, chap 16):
// starts/stops a recording
OnCheckedChangeListener recordButtonListener =
new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
{
if (isChecked)
{
visualizer.clear(); // clear visualizer for next recording
saveButton.setEnabled(false); // disable saveButton
deleteButton.setEnabled(false); // disable deleteButton
viewSavedRecordingsButton.setEnabled(false); // disable
// create MediaRecorder and configure recording options
if (recorder == null)
recorder = new MediaRecorder(); // create MediaRecorder
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(
MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioEncodingBitRate(16);
recorder.setAudioSamplingRate(44100);
try
{
// create temporary file to store recording
File tempFile = File.createTempFile(
"VoiceRecorder", ".3gp", getExternalFilesDir(null));
// store File as tag for saveButton and deleteButton
saveButton.setTag(tempFile);
deleteButton.setTag(tempFile);
// set the MediaRecorder's output file
recorder.setOutputFile(tempFile.getAbsolutePath());
recorder.prepare(); // prepare to record
recorder.start(); // start recording
recording = true; // we are currently recording
handler.post(updateVisualizer); // start updating view
} // end try
catch (IllegalStateException e)
{
Log.e(TAG, e.toString());
} // end catch
catch (IOException e)
{
Log.e(TAG, e.toString());
} // end catch
} // end if
else
{
recorder.stop(); // stop recording
recorder.reset(); // reset the MediaRecorder
recording = false; // we are no longer recording
saveButton.setEnabled(true); // enable saveButton
deleteButton.setEnabled(true); // enable deleteButton
recordButton.setEnabled(false); // disable recordButton
} // end else
} // end method onCheckedChanged
}; // end OnCheckedChangedListener
In a debug session, the "else" scope is entered but it hangs on its first (stop()) line.
I repeat, I know the phone and its OS are correct because another app works correctly. So, do you have any idea on how to solve this problem, a work around maybe?
Thanks!
EDIT When the recorder is started(), there is a handler that is executed at each 50ms to display a graph of the amplitude of the sound. The method recorder.getMaxAmplitude() always returns 0. Maybe this is the symptom of a badly initialized MediaRecorder?
The argument of setAudioEncodingBitRate() might be too low.
what is good setAudioEncodingBitRate on record voice
Hope that's help.
You could have a null recorder at that spot. You're not creating a new MediaRecorder() if you enter the else case of isChecked.
So, 2 things:
The API docs state that if you call stop() before start you'll throw a RuntimeException And if you fail to record anything you'll throw an IllegalStateException.
Check recorder before calling stop:
if (recorder != null) {
recorder.stop();
// some recorder stuff here
}

Auto reset Video recording Android

I am working on a application where I need to record video on a button click of predefined lenth say 15 sec. After 15 sec I want to reset the MediaRecorder automatically without manual intervation My code is here.
public void initMediaRecorder(){
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
mRecorder.setPreviewDisplay(mHolder.getSurface());
mRecorder.setMaxDuration(15000);
mRecorder.setOutputfile("blahblah On SD card")
mRecorder.setOutputFile(mOutputFile);
}
Now the recording is getting done but after 15sec my UI is getting freeze and I need to reset manually the recorder. I need to know the event on which I should reset the recorder after 15sec time is done.
I found out the solution.
Maybe this answer will help some one.
Use the following listener
recorder.setOnInfoListener(new medialistener());
class medialistener implements MediaRecorder.OnInfoListener {
public void onInfo(MediaRecorder recorder, int what, int extra)
{
if(what==MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
{
}
// Log.i("video test", "Video Info: "+what+", "+extra);
}
}
cheers.

MediaPlayer setDisplay when returning to an activity not working

I want to play video with MediaPlayer in the background so when the user leave my app he will still hear the audio and when he is returning to the app he will see the video. I managed to do the first part with Service that plays the MediaPlayer, but I have a problem in the second part. When I leave the app and return the video does not show in the SurfaceView.
When the user return I created new Surface, so I tried this:
public void surfaceCreated(SurfaceHolder holder) {
if(mService!=null && mService.player.isPlaying()){
try {
mService.player.setDisplay(holder);
mService.player.prepare();
mService.player.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
While mService is my Service and he holds the MediaPlayer player.
In my research I saw this post:
Black screen when returning to video playback activity in Android
But this was posted a year ago so maybe anyone has any different and new answer.
EDIT:
I forgot to say that the video is streaming, so reset is not good option (i tried :)).
is it possible to save the SurfaceView in the Service and when the user return to take the view and add it dynamically to the current layout?
When you first launch Activity: onResume()->onSurfaceCreated()->onSurfaceChanged().
When you leave Activity: onPause()->onSurfaceDestroyed()
So i you leave your app, surface will be automatically destroy, you also can not save surfaceview in service.
Remember, if you want to show video again, surfaceview and holder callback must created again in onStart in case your home or lockscreen pressed
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.setFixedSize(800, 480);
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

MediaPlayer.prepare is throwing an IllegalStateException when playing m4a file

I have a list of songs that I'm streaming using the MediaPlayer. Some of the songs consistently work and others consistently do not work. I can't see a difference between these files, and they seem to play fine in itunes and such.
When the songs fail it is throwing an IllegalStateException on the mediaPlayer.prepare() line. The IllegalStateException that is thrown has no useful info in it, (detailMessage is null, stackState is null)
Here is my code
try {
mediaPlayer.setDataSource(media.url);
setPlayerState(PlayerState.PREPARING);
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
Here is a url to the file that does NOT work:
skdy.bryceb.dev.mediarain.com/song.m4a
Here is one that DOES work:
skdy.bryceb.dev.mediarain.com/song2.m4a
Any ideas why this works on some songs and fails on others?
Thanks MisterSquonk I'm sure that way would work.
In my particular case after beating my head against the wall for a while I realized that on some songs, I was getting to the buffered amount before the player state was getting set to prepared. So I added a check to make sure that the MediaPlayer was in the "PREPARED" state and then it worked great:
// Media prepared listener
mediaPlayer.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
setPlayerState(PlayerState.PREPARED);
}
});
// Media buffer listener
mediaPlayer.setOnBufferingUpdateListener(
new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// Sometimes the song will finish playing before the 100% loaded in has been
// dispatched, which result in the song playing again, so check to see if the
// song has completed first
if(getPlayerState() == PlayerState.COMPLETED)
return;
if(getPlayerState() == PlayerState.PAUSED)
return;
// If the music isn't already playing, and the buffer has been reached
if(!mediaPlayer.isPlaying() && percent > PERCENT_BUFFER) {
if(getPlayerState() == PlayerState.PREPARED)
{
mediaPlayer.start();
setPlayerState(PlayerState.PLAYING);
}
//if it isn't prepared, then we'll wait till the next buffering
//update
return;
}
}
});
OK, I hacked together a minimal Mediaplayer implementation in a 'sandbox' app/activity I always keep spare for testing.
I might be wrong but if you're streaming these songs over the net, you'll need to prefix the url with http://.
I tried the urls with Winamp and Chrome verbatim (no protocol prefix string) and they worked fine although it's likely both of those applications will use some form of intelligence to work out how to connect/stream.
If I tried that in my mediaPlayer code, I get the same exception as you but if I prefix the urls with http:// the songs play fine.
Example...
// Activity scope
Button button;
CheckBox checkBox;
String url = "";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//button declared in my activity
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
if (!checkBox.isChecked())
url = getString(R.string.url_song1);
else
url = getString(R.string.url_song2);
mediaPlayer = new MediaPlayer();
}
#Override
public void onClick(View arg0) {
try {
Log.i(TAG, "onClick() entered...");
mediaPlayer.setDataSource(url);
Log.i(TAG, "Preparing mediaplayer...");
mediaPlayer.prepare();
Log.i(TAG, "Starting mediaplayer...");
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
}
If I copy the songs to my SD card both play fine and as long as the internet url strings have an 'http://' prefix then they also work.

Categories

Resources