I need to record video for 8 seconds in my app. I am using MediaStore.ACTION_VIDEO_CAPTURE intent for video recording and using these parameters (MediaStore.EXTRA_VIDEO_QUALITY,MediaStore.EXTRA_DURATION_LIMIT) to set quality and duration limit of video recording. but i encountered a very interesting bug i.e. when i set duration limit to 8 seconds and video quality to 1, its working fine and is recording video for 8 seconds but as soon i changes the video quality to 0 and keeping everything same, the video is now recorded for 21 seconds. I am using sony Xperia phone for testing, but when i shift to HTC, duration limit not working in any case neither on setting video quality to 1 nor on setting it to 0.
So i don't know what is happening right now. In severe need. please help. Thanks in advance.
Here is the code I am using..
private void recordVideo() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
objectGlobal.setFilepath(filePath);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 8);
startActivityForResult(intent, CAMERA_CAPTURE_VIDEO);
}
I know its bit late to answer this question, but i think i have to, so that if others are facing this problem, they can easily deal with it.
Actually the problem is when you lower the video quality via this
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
the camera intent no longer works as a video recorder. It actually creates a mms when we try lowering the quality. As far as time is concerned, I don't know whether it is a bug in Android or may be some memory constraints. So the solution I adopted is to make custom video recording class using SurfaceView. So I am pasting the code of Video Recording from one of my projects.Also the video recorded is almost playable in all android/iOS devices, i have tested so far. Here is my Video Recording Class
package com.mukesh.videorecordingsample;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class RecordVideoPostsActivity extends Activity implements
SurfaceHolder.Callback, OnClickListener {
protected static final int RESULT_ERROR = 0x00000001;
private static final int MAX_VIDEO_DURATION = 8 * 1000;
private static final int ID_TIME_COUNT = 0x1006;
private SurfaceView mSurfaceView;
private ImageView iv_cancel, iv_ok, iv_record;
private TextView tv_counter;
private SurfaceHolder mSurfaceHolder;
private MediaRecorder mMediaRecorder;
private Camera mCamera;
private List<Size> mSupportVideoSizes;
private String filePath;
private boolean mIsRecording = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_recordvideo);
initView();
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
iv_record = (ImageView) findViewById(R.id.iv_record);
iv_cancel = (ImageView) findViewById(R.id.iv_cancel);
iv_ok = (ImageView) findViewById(R.id.iv_ok);
iv_record.setImageResource(R.drawable.btn_video_start);
tv_counter = (TextView) findViewById(R.id.timer);
tv_counter.setVisibility(View.GONE);
iv_cancel.setOnClickListener(this);
iv_ok.setOnClickListener(this);
iv_record.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
private void exit(final int resultCode, final Intent data) {
if (mIsRecording) {
new AlertDialog.Builder(RecordVideoPostsActivity.this)
.setTitle("Video Recorder")
.setMessage("Do you want to exit?")
.setPositiveButton("yes",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
stopRecord();
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
})
.setNegativeButton("no",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
}
}).show();
return;
}
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
private void deleteFile(File delFile) {
if (delFile == null) {
return;
}
final File file = new File(delFile.getAbsolutePath());
delFile = null;
new Thread() {
@Override
public void run() {
super.run();
if (file.exists()) {
file.delete();
}
}
}.start();
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ID_TIME_COUNT:
if (mIsRecording) {
if (msg.arg1 > msg.arg2) {
// mTvTimeCount.setVisibility(View.INVISIBLE);
tv_counter.setText("00:00");
stopRecord();
} else {
tv_counter.setText("00:0" + (msg.arg2 - msg.arg1));
Message msg2 = mHandler.obtainMessage(ID_TIME_COUNT,
msg.arg1 + 1, msg.arg2);
mHandler.sendMessageDelayed(msg2, 1000);
}
}
break;
default:
break;
}
}
;
};
private void openCamera() {
try {
this.mCamera = Camera.open();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(90);
System.out.println(parameters.flatten());
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
mCamera.lock();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
try {
mCamera.setDisplayOrientation(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
}
}
mSupportVideoSizes = parameters.getSupportedVideoSizes();
if (mSupportVideoSizes == null || mSupportVideoSizes.isEmpty()) {
String videoSize = parameters.get("video-size");
Log.i(EmBazaarConstants.APP_NAME, videoSize);
mSupportVideoSizes = new ArrayList<Camera.Size>();
if (!RecordVideoPostsActivity.isEmpty(videoSize)) {
String[] size = videoSize.split("x");
if (size.length > 1) {
try {
int width = Integer.parseInt(size[0]);
int height = Integer.parseInt(size[1]);
mSupportVideoSizes.add(mCamera.new Size(width,
height));
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, e.toString());
}
}
}
}
for (Size size : mSupportVideoSizes) {
Log.i(EmBazaarConstants.APP_NAME, size.width + "<>" + size.height);
}
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, "Open Camera error\n" + e.toString());
}
}
private boolean initVideoRecorder() {
if (mCamera == null) {
mCamera = Camera.open();
mCamera.unlock();
} else {
mCamera.unlock();
}
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
try {
CamcorderProfile lowProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_LOW);
CamcorderProfile hightProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
if (lowProfile != null && hightProfile != null) {
lowProfile.audioCodec = MediaRecorder.AudioEncoder.AAC;
lowProfile.duration = hightProfile.duration;
lowProfile.videoCodec = MediaRecorder.VideoEncoder.H264;
lowProfile.videoFrameRate = hightProfile.videoFrameRate;
lowProfile.videoBitRate = 1500000 > hightProfile.videoBitRate ? hightProfile.videoBitRate
: 1500000;
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
int width = 640;
int height = 480;
Collections.sort(mSupportVideoSizes, new SizeComparator());
int lwd = mSupportVideoSizes.get(0).width;
for (Size size : mSupportVideoSizes) {
int wd = Math.abs(size.width - 640);
if (wd < lwd) {
width = size.width;
height = size.height;
lwd = wd;
} else {
break;
}
}
lowProfile.videoFrameWidth = width;
lowProfile.videoFrameHeight = height;
}
mMediaRecorder.setProfile(lowProfile);
}
} catch (Exception e) {
try {
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
} catch (Exception ex) {
ex.printStackTrace();
}
try {
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
} catch (Exception ex) {
ex.printStackTrace();
}
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
Collections.sort(mSupportVideoSizes, new SizeComparator());
Size size = mSupportVideoSizes.get(0);
try {
mMediaRecorder.setVideoSize(size.width, size.height);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
try {
mMediaRecorder.setVideoSize(640, 480);
} catch (Exception ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
}
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
mMediaRecorder.setOutputFile(filePath);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
try {
mMediaRecorder.setOrientationHint(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d("VideoPreview",
"IllegalStateException preparing MediaRecorder: "
+ e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d("VideoPreview",
"IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (Exception e) {
releaseMediaRecorder();
e.printStackTrace();
}
return true;
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
mCamera.lock();
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private void startRecord() {
try {
if (initVideoRecorder()) {
mMediaRecorder.start();
iv_record.setImageResource(R.drawable.btn_video_stop);
} else {
releaseMediaRecorder();
iv_record.setImageResource(R.drawable.btn_video_start);
}
tv_counter.setVisibility(View.VISIBLE);
tv_counter.setText("00:0" + (MAX_VIDEO_DURATION / 1000));
Message msg = mHandler.obtainMessage(ID_TIME_COUNT, 1,
MAX_VIDEO_DURATION / 1000);
mHandler.sendMessage(msg);
mIsRecording = true;
} catch (Exception e) {
showShortToast("problem while capturing video");
e.printStackTrace();
exit(RESULT_ERROR, null);
}
}
private void stopRecord() {
try {
mMediaRecorder.stop();
} catch (Exception e) {
if (new File(filePath) != null
&& new File(filePath).exists()) {
new File(filePath).delete();
}
}
releaseMediaRecorder();
mCamera.lock();
iv_record.setImageResource(R.drawable.btn_video_start);
mIsRecording = false;
iv_record.setVisibility(View.GONE);
iv_cancel.setVisibility(View.VISIBLE);
iv_ok.setVisibility(View.VISIBLE);
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo(); // Since API level 9
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
@Override
protected void onResume() {
super.onResume();
openCamera();
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (Exception e) {
}
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.stopPreview();
} catch (Exception e) {
}
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit(RESULT_CANCELED, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.iv_ok:
Intent data = new Intent();
if (filePath != null) {
data.putExtra("videopath", filePath);
}
exit(RESULT_OK, data);
break;
case R.id.iv_cancel:
exit(RESULT_CANCELED, null);
break;
case R.id.iv_record:
if (mIsRecording) {
stopRecord();
} else {
startRecord();
}
break;
default:
break;
}
}
protected void showShortToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
private File setUpVideoFile() throws IOException {
File videoFile = null;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
File storageDir = new File(
EmBazaarConstants.LOCAL_STORAGE_BASE_PATH_FOR_POSTED_VIDEOS)
.getParentFile();
if (storageDir != null) {
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
}
videoFile = File.createTempFile(EmBazaarConstants.MP4_FILE_PREFIX
+ System.currentTimeMillis() + "_",
EmBazaarConstants.MP4_FILE_SUFIX, storageDir);
} else {
Log.v(getString(R.string.app_name),
"External storage is not mounted READ/WRITE.");
}
return videoFile;
}
private class SizeComparator implements Comparator<Size> {
@Override
public int compare(Size lhs, Size rhs) {
return rhs.width - lhs.width;
}
}
public static boolean isEmpty(String str) {
return str == null || "".equals(str.trim());
}
}
and you can simply call this class in your Activity like this
if (isDeviceSupportCamera()) {
startActivityForResult(new Intent(PostStatusActivity.this,
yourActivity.class),
EmBazaarConstants.CAMERA_CAPTURE_VIDEO);
} else {
Toast.makeText(this, "Your device doesn't support camera",
Toast.LENGTH_LONG).show();
}
and here is isDeviceSupportCamera() function
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
In your onActivityResult, you have to write this code
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == EmBazaarConstants.CAMERA_CAPTURE_VIDEO
&& resultCode == RESULT_OK) {
if (data != null && data.getStringExtra("videopath") != null)
videoFilePath= data.getStringExtra("videopath");
}
}
Hope this helps.
** Although we have new Camera2 APIs in android lollipop, but this code still works in android lollipop as well.But still you can change to new Camera2 APIs,if you want.