Hi I am trying to work on a hardware camera control in android,
I am able to get the preview of the camera on the surface view,
however I am unable to record any video, as on starting the video recording I get the following error:
Media server died
Camera server died
ICamera died
error 100
the code for capture is as under
public void onCaptureClick(View view){
if(!isRecording)
new MediaPrepareTask().execute(null,null,null);
else{
mMediaRecorder.stop();
releaseMediaRecorder();
mCamera.lock();
setCaptureButtonText("Start");
isRecording = false ;
releaseCamera();
}
}
This is the media prepare task
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean>{
#Override
protected Boolean doInBackground(Void... arg0) {
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
Log.i(TAG,"Media recording started");
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
return false;
}
return true;
}
#Override
protected void onPostExecute(Boolean result){
if(!result){
MainActivity.this.finish();
}
setCaptureButtonText("Stop");
}
}
This is where I set the property for recording
private boolean prepareVideoRecorder(){
Log.i(TAG,"Starting to prepare");
Camera.Parameters parameters = mCamera.getParameters() ;
Log.i(TAG,"Got Property");
List<Camera.Size> mSupportedPreviewSize = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSize,
mPreview.getWidth(), mPreview.getHeight());
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
profile.videoFrameWidth = optimalSize.width ;
profile.videoFrameHeight = optimalSize.height ;
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
Log.i(TAG,"Set Parameters");
try{
// // mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
mCamera.setPreviewDisplay(mPreview.getHolder());
}catch(IOException iOEx){
iOEx.printStackTrace();
Log.e(TAG, "Failed to set preview display ");
return false ;
}
////////////////////////////////now for the media recorder ///////////////////////
mMediaRecorder = new MediaRecorder();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
Log.i(TAG,"Set camera for recorder");
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
mMediaRecorder.setProfile(profile);
Log.i(TAG,CameraHelper.getOutputMediaFile(CameraHelper.MEDIA_TYPE_VIDEO).toString());
mMediaRecorder.setOutputFile(CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
Log.i(TAG,"Set the ouptut format");
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
Log.i(TAG,"All is well");
return true;
}
this is for anyone reading the question
the issue is with the surface to be added to the media recorder as well,
just add the surface to the media recorder and it works
Related
I am recording a video in android using media recorder. The video is recorded nicely in phone for both front and back camera but for tablet the video is recorded nicely for back camera but for front camera it is showing blurry. This is how my recorded video looks:
my code for video recording is
private Camera getCameraInstance() {
// TODO Auto-generated method stub
Camera c = null;
try {
if (Camera.getNumberOfCameras() >= 2) {
//if you want to open front facing camera use this line
c = Camera.open(CameraInfo.CAMERA_FACING_FRONT);}
// c.setDisplayOrientation(90);
//c = Camera.open(1); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private boolean prepareMediaRecorder() {
myCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
myCamera.unlock();
mediaRecorder.setCamera(myCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
//mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
//mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder()
.getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
I'm playing with the google tutorial on using video recorders but I can't get it to work anyhow. I first keep getting at Method called after release error, for the camera preview which I tracked down to realize that mCamera.stoppreview() doesn't work before the startpreview is called again onSurfaceChanged(). Also I get a Camera 100 error with mediaserver died, camera server died and icamera died when MediaRecorder.start() is called. I can't seem to figure out why.
Here is my CameraActivity code
public class MainActivity extends Activity {
private Camera mCamera;
private MediaRecorder mMediaRecorder;
private CameraPreview mPreview;
private static final String TAG = "Message";
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private boolean isRecording = false;
Button captureButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preview);
System.out.println("Going to get the camera");
mCamera = getCameraInstance();
//mMediaRecorder = new MediaRecorder();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// setPreviewCallback(null);
captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isRecording) {
// 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
captureButton.setText("Capture");
isRecording = false;
} else {
// initialize video camera
releaseCamera();
if (prepareVideoRecorder()) {
System.out.println("Starting to record");
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
// inform the user that recording has started
captureButton.setText("Stop");
isRecording = true;
} else {
// prepare didn't work, release the camera
System.out.println("Recording failed");
releaseMediaRecorder();
// inform user
}
}
}
}
);
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open();
System.out.println("This is the camera "+c);// attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
System.out.println("Didn't get the camera ");
}
return c; // returns null if camera is unavailable
}
private boolean prepareVideoRecorder(){
mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();
/*CameraPreview preview;
preview=new CameraPreview(this, mCamera);*/
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// Step 5: Set the preview output
System.out.println("About to preview");
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
System.out.println("Preview worked");
// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
private void releaseMediaRecorder(){
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera(){
if (mCamera != null){
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
System.out.println("Picture received");
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: ");
return;
}
try {
System.out.println("Saving");
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
/** Create a File for saving an image or video */
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
System.out.println("Trying to save picture");
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
and this is my CameraPreview class
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "Message";
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
/*mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();*/
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
System.out.println("Stop preview didn't work ");
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
EDIT:
XML Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<Button
android:id="#+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
I was also able to fix this issue by removing the call to mCamera.release() in onPause(). Here's some code:
//kv Only call release here if we're running an OS later than Gingerbread, otherwise, camera will freeze
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1)
{
mCamera.release();
}
I am developing an app which should record a video of Maximum limit one minute, and saving it in gallery and then right after it saves it should start playing automatically.
Following is my code.
public class MainActivity extends Activity {
private Camera myCamera;
private MyCameraSurfaceView myCameraSurfaceView;
private MediaRecorder mediaRecorder;
Button myButton;
SurfaceHolder surfaceHolder;
boolean recording;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recording = false;
setContentView(R.layout.main);
//Get Camera for preview
myCamera = getCameraInstance();
if(myCamera == null){
Toast.makeText(MainActivity.this,
"Fail to get Camera",
Toast.LENGTH_LONG).show();
}
myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
myCameraPreview.addView(myCameraSurfaceView);
myButton = (Button)findViewById(R.id.mybutton);
myButton.setOnClickListener(myButtonOnClickListener);
Log.i("Camera !Error", "Cameray ka koi masla ni Agay chcek karo");
}
Button.OnClickListener myButtonOnClickListener
= new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(recording){
// stop recording and release camera
mediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
//Exit after saved
finish();
}else{
//Release Camera before MediaRecorder start
releaseCamera();
if(!prepareMediaRecorder()){
Toast.makeText(MainActivity.this,
"Fail in prepareMediaRecorder()!\n - Ended -",
Toast.LENGTH_LONG).show();
finish();
}
mediaRecorder.start();
recording = true;
myButton.setText("STOP");
Log.i("Camera !Error", "Record to stop");
}
}};
private Camera getCameraInstance(){
// TODO Auto-generated method stub
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
Log.i("Camera Error", "Camera Not Found");
}
Log.i("Camera Error", "Camera Found");
return c; // returns null if camera is unavailable
}
private boolean prepareMediaRecorder(){
myCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
myCamera.unlock();
mediaRecorder.setCamera(myCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setOutputFile("/sdcard/myvideo2.3gp");
mediaRecorder.setMaxDuration(10000); // Set max duration 10 sec.
mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
Log.i("Camera Error", "Media Recorder is ready");
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
private void releaseMediaRecorder(){
if (mediaRecorder != null) {
mediaRecorder.reset(); // clear recorder configuration
mediaRecorder.release(); // release the recorder object
mediaRecorder = null;
myCamera.lock(); // lock camera for later use
}
Log.i("Media Recorder", "Media Recorer Released");
}
private void releaseCamera(){
if (myCamera != null){
myCamera.release(); // release the camera for other applications
myCamera = null;
}
Log.i("Camera Recorder", "Camera Released");
}
public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public MyCameraSurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int weight,
int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
}
my main.xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/videoview"
android:layout_width="720px"
android:layout_height="480px"/>
<Button
android:id="#+id/mybutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="REC"
android:textSize="12sp"/>
</LinearLayout>
On button click recording starts and on click again, it stops and exits using
finish() for this purpose. Here i want that instead of exiting the recorded video should start.
Hope i managed to clearly explain my question.
This is the code i used to record video from an android device in MP4 format. The file is being created but is of 0 bytes size. I dont seem to understand what has gone wrong. Any help will be appreciated.
if(mCamera == null) {
mCamera = Camera.open();
mCamera.unlock();
}
if(mediaRecorder == null)
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setMaxDuration(maxDurationInMs);
mediaRecorder.setOutputFile("/sdcard/1.mp4");
mediaRecorder.setVideoFrameRate(videoFramesPerSecond);
mediaRecorder.setVideoSize(176,144);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mediaRecorder.setPreviewDisplay(surface);
mediaRecorder.setMaxFileSize(maxFileSizeInBytes);
mediaRecorder.prepare();
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
// This is thrown if the previous calls are not called with the
// proper order
e.printStackTrace();
}
mediaRecorder.start();
The reason for such behavior is that you are probably (95% sure) calling recorder.setOutputFile() again after you have finished your recording (after recorder.stop() perhaps). Thus old file is being rewritten by new empty file.
okay so i finally figured it out myself. i used the method described here and it worked properly.
http://developer.android.com/guide/topics/media/camera.html#saving-media
The Below code worked for me :
private boolean isRecording = false;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_record);
// Create an instance of Camera
mCamera = getCameraInstance();
mHolder = surfaceViewRecReadyTestimonial.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private boolean prepareVideoRecorder() {
mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(surfaceViewRecReadyTestimonial.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
#Override
public void onClick(View v) {
if (v == btnStart) {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
// inform the user that recording has started
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
// inform user
}
} else if (v == btnStop) {
if (isRecording) {
// 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
isRecording = false;
}
} }
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
/**
* Create a File for saving an image or video
*/
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "FolderName");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("FolderName", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("RecordVideo", "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public static final String rootDir = getStorageDir().concat(yours_dir);
...
mediaRecorder.setOutputFile(rootDir);
Do you have set user permission
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Is it possible to record video in a service, that is without setting the setPreviewDisplay?
I tried it on a HTC Desire, however it is throwing this info in the log,
MediaRecorder Prepare Failed: -1
CameraInput No surface is available for display
Is there some additional properties to be set?
I found this snippet somewhere. Not sure if it works for media recorder, but it was working reasonably well for camera.takePicture on HTC hero android 2.1-update1 (and simulator).
if (camera == null) {
Log.i(TAG, "Opening camera");
camera = Camera.open();
}
SurfaceView view = new SurfaceView(new DummyContext()); //You'll have to create your own class extending Context
camera.setPreviewDisplay(view.getHolder());
camera.startPreview();
//wait
Log.i(TAG, "Wait for cam");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Log.e(TAG, "Woken violently");
e.printStackTrace();
}
//take pic
Log.i(TAG, "Take pic");
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
I believe according to the docs
public final void setPreviewDisplay
(SurfaceHolder holder)
Since: API Level 1 Sets the Surface to
be used for live preview. A surface is
necessary for preview, and preview is
necessary to take pictures. The same
surface can be re-set without harm.
I know you are desiring to take video but, I take this to me any camera usage requires a surface.
public class RecorderService extends Service {
private static final String TAG = "RecorderService";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
private File filefolder;
private String strphoto;
private File photo;
#Override
public void onCreate() {
mRecordingStatus = false;
//mServiceCamera = CameraRecorder.mCamera;
mServiceCamera = Camera.open();
mSurfaceView = CameraRecorder.mSurfaceView;
mSurfaceHolder = CameraRecorder.mSurfaceHolder;
super.onCreate();
if (mRecordingStatus == false)
startRecording();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
stopRecording();
mRecordingStatus = false;
super.onDestroy();
}
public boolean startRecording(){
try {
Toast.makeText(getBaseContext(), "Recording Started", Toast.LENGTH_SHORT).show();
//mServiceCamera = Camera.open();
Camera.Parameters params = mServiceCamera.getParameters();
mServiceCamera.setParameters(params);
Camera.Parameters p = mServiceCamera.getParameters();
final List<Size> listSize = p.getSupportedPreviewSizes();
Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
filefolder=new File(android.os.Environment.getExternalStorageDirectory(),"Backgroundcamera/videos");
}
else
{
filefolder=RecorderService.this.getCacheDir();
}
if(!filefolder.exists())
filefolder.mkdirs();
strphoto = System.currentTimeMillis()+".mp4";
mMediaRecorder.setOutputFile(filefolder+"/"+strphoto);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStatus = true;
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
Toast.makeText(getBaseContext(), "Recording Stopped", Toast.LENGTH_SHORT).show();
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mServiceCamera.stopPreview();
mMediaRecorder.release();
mServiceCamera.release();
mServiceCamera = null;
}
}
and
start the service on a click listerner.