SoFunction
Updated on 2025-04-05

Android custom Camera implements photography function

This article records the simple photo-taking function implemented with custom Camera.

The Camera class is not recommended after 5.0. Instead, it is replaced by the class under the .camera2 package. This article uses Camera.
Let's first customize a View to inherit the SurfaceView:

public class CameraSurfaceView extends SurfaceView implements ,  {
 private SurfaceHolder mHolder;
 private Camera mCamera;
 private static final int ORIENTATION = 90;
 private int mScreenWidth;
 private int mScreenHeight;
 private boolean isOpen;

 public CameraSurfaceView(Context context, AttributeSet attrs) {
  super(context, attrs);
  getScreenMatrix(context);
  mHolder = getHolder();
  (this);
  (SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 }

 private void getScreenMatrix(Context context) {
  WindowManager WM = (WindowManager) (Context.WINDOW_SERVICE);
  DisplayMetrics outMetrics = new DisplayMetrics();
  ().getMetrics(outMetrics);
  mScreenWidth = ;
  mScreenHeight = ;
 }

 public void takePicture( mShutterCallback,  rawPictureCallback,  jpegPictureCallback) {
  if (mCamera != null)
   (mShutterCallback, rawPictureCallback, jpegPictureCallback);
 }

 public void startPreview() {
  ();
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  if (!checkCameraHardware(getContext()))
   return;
  if (mCamera == null) {
   isOpen = safeCameraOpen(.CAMERA_FACING_BACK);
  }
  if (!isOpen) {
   return;
  }
  (ORIENTATION);
  try {
   (holder);

  } catch (IOException e) {
   ();
  }
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  if (mCamera != null) {
   setCameraParams(mScreenWidth, mScreenHeight);
   ();
  }
 }

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

 private boolean safeCameraOpen(int id) {
  boolean qOpened = false;
  try {
   releaseCameraAndPreview();
   mCamera = (id);
   qOpened = (mCamera != null);
  } catch (Exception e) {
   ();
  }

  return qOpened;
 }

 private void releaseCameraAndPreview() {
  if (mCamera != null) {
   ();
   ();
   mCamera = null;
  }
 }

 private boolean checkCameraHardware(Context context) {
  if (().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
   return true;
  } else {
   return false;
  }
 }


 @Override
 public void onAutoFocus(boolean success, Camera camera) {

 }

 private void setCameraParams(int width, int height) {
   parameters = ();
  // Get the PictureSize list supported by the camera  List<> pictureSizeList = ();
  /**Select the appropriate resolution from the list*/
   picSize = getProperSize(pictureSizeList, ((float) height / width));
  if (null == picSize) {
   picSize = ();
  }
  //Reset the SurfaceView size according to the selected PictureSize  float w = ;
  float h = ;
  (, );
  (new ((int) (height * (h / w)), height));
  // Get the PreviewSize list supported by the camera  List<> previewSizeList = ();
   preSize = getProperSize(previewSizeList, ((float) height) / width);
  if (null != preSize) {
   (, );
  }

  (100); // Set photo quality  if (().contains(.FOCUS_MODE_CONTINUOUS_PICTURE)) {
   (.FOCUS_MODE_CONTINUOUS_PICTURE);// Continuous Focus Mode  }

  (90);// Set the direction of PreviewDisplay, the effect is to rotate the captured screen to display how many degrees  (parameters);

 }

 /**
   * Choose the right resolution
   */
 private  getProperSize(List<> pictureSizeList, float screenRatio) {
   result = null;
  for ( size : pictureSizeList) {
   float currentRatio = ((float) ) / ;
   if (currentRatio - screenRatio == 0) {
    result = size;
    break;
   }
  }

  if (null == result) {
   for ( size : pictureSizeList) {
    float curRatio = ((float) ) / ;
    if (curRatio == 4f / 3) {// Default w:h = 4:3     result = size;
     break;
    }
   }
  }

  return result;
 }
}

The code is not difficult. Complete the initialization of Camera when the View is created, and then set the parameters of Camera (image size, quality, etc.). Finally, don't forget to release the resources when the View is destroyed.

After the control is defined, we need to use it and add it to the layout file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:andro
 android:
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 >

 <
  android:
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="4"/>

 <ImageView
  android:
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:layout_alignParentRight="true"
  android:layout_gravity="bottom"
  android:layout_marginBottom="10dp"
  android:layout_marginRight="10dp"
  android:src="@mipmap/icon_camera"/>
</RelativeLayout>

Then complete the photo function in Activity:

 

public class CameraActivity extends AppCompatActivity {
 private boolean isClick = true;
 private static final String PATH_IMAGES = ().getAbsolutePath() +  + "easy_check";
 private CameraSurfaceView mCameraSurfaceView;
 //Callback of photo shutter private  mShutterCallback = new () {
  @Override
  public void onShutter() {

  }
 };
 //A callback to return to the original data after taking the photo private  rawPictureCallback = new () {
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {

  }
 };
 //A callback to return to compressed data after taking the photo private  jpegPictureCallback = new () {
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {
   ();
   saveFile(data);
   (, "Photo taken successfully", Toast.LENGTH_SHORT).show();
   isClick = true;

  }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  (savedInstanceState);
  setContentView(.activity_main);
  ImageView img_take_photo = (ImageView) findViewById(.img_take_photo);
  mCameraSurfaceView = (CameraSurfaceView) findViewById(.sv_camera);
  img_take_photo.setOnClickListener(new () {
   @Override
   public void onClick(View v) {
    takePhoto();
   }
  });
 }

 public void takePhoto() {
  if (isClick) {
   isClick = false;
   (mShutterCallback, rawPictureCallback, jpegPictureCallback);
  }
 }
 //Save the picture to the hard disk public void saveFile(byte[] data) {
  String fileName = ().toString() + ".jpg";
  FileOutputStream outputStream = null;
  try {
   File file = new File(PATH_IMAGES);
   if (!()) {
    ();
   }
   outputStream = new FileOutputStream(PATH_IMAGES +  + fileName);
   BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
   (data, 0, );
  } catch (Exception e) {
   ();
  } finally {
   try {
    ();
   } catch (IOException e) {
    ();
   }
  }
 }
}

Finally, remember to add photo and disk operation permissions:

<uses-permission android:name=""/>
<uses-permission android:name=".WRITE_EXTERNAL_STORAGE"/>

This is a very simple photo demo that can be completed. It can only be used as a demo. There is still a long way to go before the official use of the hair. I will record it again.

download:Source code

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.