I have strange problem with my MediaRecorder. It records voice, make a file with recording. But when I want to stop recording using stop() method, it throws IllegalStateException. Generally I have used setMaxDuration() method, so usually I have ending recording using OnInfoListener and it works properly. But I want also to stop MediaRecorder in the OnTouchListener of the ImageView. My code is here:
private static String OUTPUT_FILE;
private void prepareRecording() throws Exception {
OUTPUT_FILE = "/sdcard/temp.3gpp";
File outFile = new File(OUTPUT_FILE);
if (outFile.exists())
outFile.delete();
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(OUTPUT_FILE);
recorder.setMaxDuration(10000);
try {
recorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
}
private void startRecording() {
ImageView image = (ImageView) this.findViewById(R.id.image);
image.post(new Runnable() {
#Override
public void run() {
try {
prepareRecording();
} catch (Exception e) {
e.printStackTrace();
}
image.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (recorder != null)
recorder.stop();
return true;
}
});
recorder.setOnInfoListener(new OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (recorder != null && what == 800){
recorder.stop();
}
}
});
}});
}
When I have touched the ImageView I have FATAL EXCEPTION java.lang.IllegalStateException at the line with code recorder.stop(). I have tested my code and I have realized that MediaRecorder seems to be not started. Therefore I have IllegalStateException at recorder.stop(). But when recording stops, I can find on my sdcard recording file. Whats wrong with my code?
I have also AnimationDrawable connected to the my image. It works properly.
I have resolved my problem. It is necessary to start new thread in onTouch method to avoid eceptions.
image.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Thread thread = new Thread(){
public void run(){
if (recorder != null)
recorder.stop();
}
};
thread.start();
return false;
}
});
Related
I wanna record video and audio using MediaRecorder.
It's work.
But when i check output file.
I can't play output video file.
Because,
output filesize is 0 byte.
also video time is 0 second..
Please check my code.
public class Talk extends Activity implements SurfaceHolder.Callback{
Context context;
SurfaceView sfv_Preview;
private SurfaceHolder holder;
private MediaRecorder recorder = null;
boolean recording = false;
private static final String OUTPUT_FILE = "/sdcard/videooutput.mp4";
private static final String OUTPUT_FILE_NAME = "videooutput.mp4";
private static final int RECORDING_TIME = 10000;
//Uri fileUri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_talk);
recorder = new MediaRecorder();
initRecorder();
sfv_Preview = (SurfaceView) findViewById(R.id.sfv_Preview);
holder = sfv_Preview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
context = this;
((ImageButton)findViewById(R.id.ibt_Record)).setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
recorder.start();
Log.d("recod", "start");
}
else if (MotionEvent.ACTION_UP == event.getAction() || event.getAction() == MotionEvent.ACTION_CANCEL) {
Log.d("recod", "stop");
recorder.stop();
initRecorder();
prepareRecorder();
}
return false;
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
prepareRecorder();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (recording) {
recorder.stop();
recording = false;
}
recorder.release();
finish();
}
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
recorder.setOutputFile(OUTPUT_FILE);
recorder.setMaxDuration(RECORDING_TIME);
recorder.setMaxFileSize(10485760); // Approximately 5 megabytes
}
private void prepareRecorder() {
recorder.setPreviewDisplay(holder.getSurface());
//recorder.setOrientationHint(90);
try {
recorder.prepare();
//finish();
} catch (IllegalStateException e) {
e.printStackTrace();
//finish();
} catch (IOException e) {
e.printStackTrace();
//finish();
}
}
}
What is problem?
In the else pare of your code you are doing :
recorder.stop();
initRecorder(); -->> "Problem is here"
Problem is here :
After finish recording call to method initRecorder();
which has following line of code
recorder.setOutputFile(OUTPUT_FILE);
It has same file path.
Which rewrites old file by new empty file.
To avoid this use timestamp with file name like this:
private File getVideoFile() {
File videoDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "VideoList");
// Create parent directory
if (!videoDir.exists()) {
if (!videoDir.mkdirs()) {
Log.d("ZZZ", "failed to create directory");
return null;
}
}
// Create a video file
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File videoFile;
videoFile = new File(videoDir.getPath() + File.separator +
"REC_" + timeStamp + ".mp4");
return videoFile;
}
Now method initRecorder() would look like this :
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
// recorder.setOutputFile(OUTPUT_FILE);//OLD
recorder.setOutputFile(getVideoFile());// NEW
recorder.setMaxDuration(RECORDING_TIME);
recorder.setMaxFileSize(10485760); // Approximately 5 megabytes
}
I am trying to Record a Video, But It's getting crash at Media Record starts and Media Record Prepare .please Help Me... Here Is My Code...
private boolean startRecording() {
camera.unlock();
try {
mediaRecorder = new MediaRecorder();
mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.i(TAG, "Error");
}
});
second=0;
minute=0;
recordCountTimer = new CountDownTimer(Long.MAX_VALUE,1000) {
#Override
public void onTick(long millisUntilFinished) {
second++;
if(second>=60){
second=0;
minute++;
}
recordCount.setText(String.format("%02d:%02d",minute,second));
}
#Override
public void onFinish() {
finish();
}
}.start();
mediaRecorder.setCamera(camera);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
Log.d(TAG, "A");
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
Log.e(TAG, "B");
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
defaultVideoPath= FileManger.getOutputMediaFile(MEDIA_TYPE_VIDEO).getAbsolutePath();
// uriVid = Uri.parse(FileManger.getOutputMediaFile(MEDIA_TYPE_VIDEO).getAbsolutePath());
// defaultVideoPath = getRealPathFromUri(uriVid);
mediaRecorder.setOutputFile(defaultVideoPath);
mediaRecorder.setVideoSize(recordingCameraSurface.getWidth(), recordingCameraSurface.getHeight());
mediaRecorder.setVideoFrameRate(20);
Log.v(TAG, "C");
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setMaxFileSize(50000);
mediaRecorder.prepare();
Log.w(TAG, "D");
mediaRecorder.start();
Log.e(TAG, "E");
} catch (IOException e) {
releaseMediaRecorder();
return false;
}catch (IllegalStateException t){
releaseMediaRecorder();
return false;
}
return true;
}
It's giving like
RECORDER_OK﹕ B
MediaRecorder﹕ setOutputFormat called in an invalid state: 4
and Here I am Going to next Activity:
Intent intent = new Intent(RecordBuyPage.this,CheckAndSaveActivity.class);
intent.putExtra("VIDEOFILEPATH", defaultVideoPath);
startActivity(intent);
and in the next Activity i am getting the path null like:
player.setDataSource(getIntent().getStringExtra("VIDEOFILEPATH"));
I think My Order Of Calling Media Recorder Is Correct But it also getting trouble at:
mediarecoreder.prepare().
Please Give Some Valid Solution, I tried a lot From Stack overflow, but it's not working.... I think Video Is Not Recording, because when I passed it through intent it's taking null...
I hope you followed this link of sample code(Media Recorder)
https://github.com/googlesamples/android-MediaRecorder
and it has some bugs in it to record media in portrait mode so to fix this issue please follow this link
and in this link you will get your media path where it stored and you can easily pass it to another activity. Have a look I hope it helps you.
to get the path of media on stop capturing you can do this on your CaptureClick method
Log.d("Video file path", CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
and complete button OnClickListener
public void onCaptureClick(View view) {
if (isRecording) {
// BEGIN_INCLUDE(stop_release_media_recorder)
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock(); // take camera access back from MediaRecorder
// inform the user that recording has stopped
setCaptureButtonText("Capture");
isRecording = false;
releaseCamera();
Log.d("Video file path", CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
// END_INCLUDE(stop_release_media_recorder)
} else {
// BEGIN_INCLUDE(prepare_start_media_recorder)
new MediaPrepareTask().execute(null, null, null);
// END_INCLUDE(prepare_start_media_recorder)
}
}
Please follow these two links provided above, it might solve your issue.
try this
public class VideoCapture extends Activity implements OnClickListener
,SurfaceHolder.Callback {
MediaRecorder recorder;
SurfaceHolder holder;
boolean recording = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
recorder = new MediaRecorder();
initRecorder();
setContentView(R.layout.main);
SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
holder = cameraView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
}
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
recorder.setOutputFile("/sdcard/videocapture_example.mp4");
recorder.setMaxDuration(50000); // 50 seconds
recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
}
private void prepareRecorder() {
recorder.setPreviewDisplay(holder.getSurface());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
public void onClick(View v) {
if (recording) {
recorder.stop();
recording = false;
// Let's initRecorder so we can record again
initRecorder();
prepareRecorder();
} else {
recording = true;
recorder.start();
}
}
public void surfaceCreated(SurfaceHolder holder) {
prepareRecorder();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (recording) {
recorder.stop();
recording = false;
}
recorder.release();
finish();
}
}
Include Permissions in Manifest file :
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
My problem is really simple: I'm using a MediaRecorder to record voice while the user is pressing on a FAB, and playing it afterwards (when he/she releases). The issue is that I lose a few seconds near the end of the recording, and I can't figure out why (they never get played back). Code (only relevant parts are shown):
Variables
double record_length = 0;
boolean recording = false;
String outputFile;
Handler myHandler = new Handler();
MediaRecorder recorder = new MediaRecorder();
OnTouchListener
findViewById(R.id.record_record).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
findViewById(R.id.delete_swipe).setVisibility(View.VISIBLE);
StartRecord();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if(recording){
EndRecord();
}
findViewById(R.id.delete_swipe).setVisibility(View.INVISIBLE);
}
return true;
}
});
.
public void StartRecord() {
recording = true;
record_length = 0;
SharedPreferences saved_login = getSharedPreferences("FalloundLogin", 0);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
//removed construction of outputFile, but it is generated correctly - I checked
recorder.setOutputFile(outputFile);
try {
recorder.prepare();
recorder.start();
} catch (IOException e) {
e.printStackTrace();
}
myHandler.postDelayed(UpdateUploadLength, 200);
}
.
public void EndRecord() {
recording = false;
try {
recorder.stop();
recorder.reset();
recorder = null;
} catch (IllegalStateException e) {
e.printStackTrace();
}
MediaPlayer m = new MediaPlayer();
try {
m.setDataSource(outputFile);
} catch (IOException e) {
e.printStackTrace();
}
try {
m.prepare();
} catch (IOException e) {
e.printStackTrace();
}
m.start();
}
I need the recording to be a maximum of 27 seconds. To avoid complications, I tested without this extra termination condition and am including the Runnable just for completeness.
private Runnable UpdateUploadLength = new Runnable(){
#Override
public void run() {
if(recording == true) {
record_length += 0.2;
if (record_length < 27) {
myHandler.postDelayed(UpdateUploadLength, 200);
} else {
//TODO: stop recording
myHandler.removeCallbacks(UpdateUploadLength);
}
}
};
I've been trying for a few hours with no luck, so any help is appreciated (also - and I dunno if it's bad to ask multiple questions in the same post - but is there any way to get better audio quality from MediaRecorder?)
Thanks in advance.
Its answear for your second question. Yes you can have much better quality. There is more encoding types, file formats and parameters in library. Example:
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setAudioEncodingBitRate(256000);
this code will set your recorder to m4a files with AAC, 44,1kHz sampling rate and around 256kbps
in my android app , i need to record audio for only 1 min? can any one help me to record audio for a certain amount of time? i ve written a code for recording audio and it will stop only when the stop button is pressed but i need to stop recording automatically after 1 min...
here my code .. but it doesnt work
try {
recorder.prepare();
recorder.start();
//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(AudioRecordingActivity.this, "record successfullly ",
Toast.LENGTH_SHORT).show();
i1=i1+1;
}
});
//Called each time when 1000 milliseconds (1 second) (the period parameter)
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
10*1000);
if (null != recorder) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
Toast.makeText(AudioRecordingActivity.this, "record successfullly",
Toast.LENGTH_SHORT).show();
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Try below code
recorder.start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
recorder.stop();
}
}, 60000);
Try recorder.setMaxDuration(60*1000);
Or, if you need to do this repeatetly, use above answer, but add
if (null == recorder)
{
recorder = new MediaRecorder();
} else recorder.reset();
This approach more likely :)
Use below code.
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(getFilename());
recorder.setOnErrorListener(errorListener);
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
new Timer().schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (null != recorder) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
}
});
}
}, 60000);
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I have an application that has a few buttons that have sounds (soundPool) I need to write them down on a flash card I make it through the MediaRecorder but when I run the app and then turn on the record playing and click stop recording application crashes you do not tell me what the problem is?
I expect that in the method recordStop
public class MainActivity extends Activity {
int kickSound;
SoundPool mSoundPool;
AssetManager assets;
private MediaRecorder mediaRecorder;
private MediaPlayer mediaPlayer;
private String fileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSoundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
assets = getAssets();
kickSound = loadSound("snare_trap.ogg");
ImageButton kick = (ImageButton)this.findViewById(R.id.imageButton1);
kick.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
playSound(kickSound);
}
return false;
}
});
fileName = Environment.getExternalStorageDirectory() + "/record.3gpp";
}
protected void playSound(int sound) {
if (sound > 0)
mSoundPool.play(sound, 1, 1, 1, 0, 1);
}
private int loadSound(String fileName) {
AssetFileDescriptor afd = null;
try {
afd = assets.openFd(fileName);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Couldn't load file '" + fileName + "'", Toast.LENGTH_SHORT).show();
return -1;
}
return mSoundPool.load(afd, 1);
}
public void recordStart(View v) {
try {
releaseRecorder();
File outFile = new File(fileName);
if (outFile.exists()) {
outFile.delete();
}
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(AudioManager.STREAM_MUSIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setOutputFile(fileName);
mediaRecorder.prepare();
mediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void recordStop(View v) {
mediaRecorder.stop();
}
public void playStart(View v) {
try {
releasePlayer();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(fileName);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void playStop(View v) {
if (mediaPlayer != null) {
mediaPlayer.stop();
}
}
private void releaseRecorder() {
if (mediaRecorder != null) {
mediaRecorder.release();
mediaRecorder = null;
}
}
private void releasePlayer() {
mediaPlayer.release();
mediaPlayer = null;
}
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
releaseRecorder();
}
}
Why are you releasing the recorder to start out with? Releasing should only be used if you don't want to access the recorder anymore. Try moving the release to the end.