Lesson 133. Camera. Take a picture and write a video

Lesson 133. Camera. Take a picture and write a video


In this lesson:

– take a picture
– writing a video

In the last lesson, we looked at how to properly output images from the camera to the screen. Now let’s learn how to save this image as a photo and a video.

Photo is made quite simply, in one method. MediaRecorder helps us to record videos. Let me remind you that we covered MediaRecorder in detail in Lesson 129.

In order not to complicate the lesson and example, I will not bother here with the sizes of previews and screen, with turns and with the description of work with the camera. If you need more details, check out Lesson 132.

Let’s create a project:

Project name: P1331_CameraRecord
Build Target: Android 2.3.3
Application name: CameraRecord
Package name: ru.startandroid.develop.p1331camerarecord
Create Activity: MainActivity

IN strings.xml add rows:

Picture
Start
Stop

screen main.xml:



    
    
    
    
    

On the screen we have SurfaceView and three buttons: take a photo, start recording, stop recording.

In the manifesto write the permissions:



These are camera work, sound recording and sd card recording.

MainActivity.java:

package ru.startandroid.develop.p1331camerarecord;

import java.io.File;
import java.io.FileOutputStream;

import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class MainActivity extends Activity {

  SurfaceView surfaceView;
  Camera camera;
  MediaRecorder mediaRecorder;

  File photoFile;
  File videoFile;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    File pictures = Environment
        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    photoFile = new File(pictures, "myphoto.jpg");
    videoFile = new File(pictures, "myvideo.3gp");

    surfaceView = (SurfaceView) findViewById(R.id.surfaceView);

    SurfaceHolder holder = surfaceView.getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {
      @Override
      public void surfaceCreated(SurfaceHolder holder) {
        try {
          camera.setPreviewDisplay(holder);
          camera.startPreview();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }

      @Override
      public void surfaceChanged(SurfaceHolder holder, int format,
          int width, int height) {
      }

      @Override
      public void surfaceDestroyed(SurfaceHolder holder) {
      }
    });

  }

  @Override
  protected void onResume() {
    super.onResume();
    camera = Camera.open();
  }

  @Override
  protected void onPause() {
    super.onPause();
    releaseMediaRecorder();
    if (camera != null)
      camera.release();
    camera = null;
  }

  public void onClickPicture(View view) {
    camera.takePicture(null, null, new PictureCallback() {
      @Override
      public void onPictureTaken(byte[] data, Camera camera) {
        try {
          FileOutputStream fos = new FileOutputStream(photoFile);
          fos.write(data);
          fos.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });

  }

  public void onClickStartRecord(View view) {
    if (prepareVideoRecorder()) {
      mediaRecorder.start();
    } else {
      releaseMediaRecorder();
    }
  }

  public void onClickStopRecord(View view) {
    if (mediaRecorder != null) {
      mediaRecorder.stop();
      releaseMediaRecorder();
    }
  }

  private boolean prepareVideoRecorder() {

    camera.unlock();

    mediaRecorder = new MediaRecorder();

    mediaRecorder.setCamera(camera);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    mediaRecorder.setProfile(CamcorderProfile
        .get(CamcorderProfile.QUALITY_HIGH));
    mediaRecorder.setOutputFile(videoFile.getAbsolutePath());
    mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface());

    try {
      mediaRecorder.prepare();
    } catch (Exception e) {
      e.printStackTrace();
      releaseMediaRecorder();
      return false;
    }
    return true;
  }

  private void releaseMediaRecorder() {
    if (mediaRecorder != null) {
      mediaRecorder.reset();
      mediaRecorder.release();
      mediaRecorder = null;
      camera.lock();
    }
  }

}

see the code

IN onCreate we create paths for photos and video files that will store the result. Next we define SurfaceView, Holder and callback to it.

IN onResume access the camera.

IN onPause release MediaRecorder resources and cameras.

onClickPicture is a Picture Click Processor. Here we will take a picture. To do this, we need to call the takePicture method. This method is asynchronous, callbacks are used to get the result. There are three of them.

The first, ShutterCallback, will work as soon as the camera takes the picture. You can hang the shutter sound, for example. I don’t use it, pass null.

The second, PictureCallback, will return the raw raw picture to us. I also do not use it, pass null.

The third one, PictureCallback, will return a ready-made jpeg image to us. That’s what we need. We create a callback and in its method onPictureTaken we will receive a byte-array. This is the finished photo that we write in the file.

onClickStartRecord – Start button click handler. Here we will include video recording from the camera. To do this, we prepare MediaRecorder in the prepareVideoRecorder method. The method will return us the value of Boolean, by which we will understand whether the object could be prepared. If it is ready, start the entry using the start method. If there are problems with preparation, then we free up resources.

onClickStopRecord – Stop button handler. Here we stop video recording by the stop method and free up resources. By the way, the help to the stop method says that it can issue a RuntimeException if something is wrong with the audio / video that MediaRecorder gave to the input. It makes sense to catch and delete the error in this case, because there will be incorrect data.

prepareVideoRecorder – a method of preparing MediaRecorder for recording. First, unlock removes monopoly access from the camera so MediaRecorder can use it. Then we create a MediaRecorder object. The following are 6 methods of setting it:

setCamera – provide the camera that will be used for recording
setAudioSource: specify the audio source – CAMCORDER
setVideoSource: We specify the video source – CAMERA
setProfile: specify the record profile. The profile contains information such as container type, audio / video codec, bit rate, and more. To prevent us from putting all these characteristics into our hands, we use profiles. You can see a list of profiles in Help to the CamcorderProfile object. We use high quality – QUALITY_HIGH.
setOutputFile: Specify the path to the file where the video will be recorded
setPreviewDisplay: Specify the surface to display previews during recording. If you have previously specified a surface for the camera in its setPreviewDisplay method, this method is optional.

Help strongly recommends that you use these 6 methods professionally in this order, otherwise it is fraught with errors and failures in recording.

When all parameters are specified, we call prepare and if everything is ok then we get MediaRecorder ready for recording.

In the method releaseMediaRecorder release MediaRecorder resources and monopolize the camera again with the lock method.

You can save and run everything. Clicking the Picture button saves the photos, and the Start and Stop buttons start and stop video recording. The resulting photos and videos will be saved in the Pictures folder under the names myphoto.jpg and myvideo.3gp

In the next lesson:

– change the camera settings




Discuss in the forum [20 replies]

Leave a Comment