The API and related knowledge of the camera have been described above, and we will explain the examples of the camera below.
Android uses camera to develop the most basic process of taking pictures:
- Use open(int cameraId) to get the camera instance.
- Set the preview class for the camera instance, which is a SurfaceHolder object, set by setPreviewDisplay(SurfaceHolder).
- Call startPreview() to start the preview of the camera instance
- Call the takePicture() method to take a picture, and the captured Image data can be obtained through the Camera.PictureCallback() callback.
- When the shooting is complete, you need to call stopPreview() to stop the preview, and use release() to release the resources occupied by the camera.
The above steps are an essential process. The camera has no public constructor, and the camera instance can only be obtained through the open() method, and a surfaceHolder preview class is set. If this step is not implemented, the camera will not be able to be used. After the camera is used, release() must be used to release the camera resource. The following examples are explained in detail.
The following example is broken down into these steps:
- System permission configuration
- camera layout
- Camera Preview Settings
- camera to take pictures
System permission configuration
// 相机权限
<uses-permission android:name="android.permission.CAMERA" />
// 文件读写权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
// 相机自动对焦配置
<uses-feature android:name="android.hardware.camera.autofocus" />
camera layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyCameraActivity">
<!--预览相机画面-->
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--两个按钮,取消和拍照-->
<LinearLayout
android:id="@+id/view_bottom_operate"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#FFF"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/btn_cancle"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:text="取消"
android:textColor="#000"
android:src="@mipmap/icon_cancle"
android:textSize="18sp" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/btn_take_picture"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:text="点击拍照"
android:textColor="#000"
android:src="@mipmap/icon_take_picture"
android:textSize="18sp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=""
android:textColor="#000"
android:textSize="18sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Camera Preview Settings
The camera preview setting needs to obtain the camera and the camera preview size first, and then display the camera preview screen through SurfaceView .
get a camera
/**
* 获取相机实例
*
* @param cameraId 相机编号
* @param degrees 预览旋转角度
* @return
*/
private Camera getCamera(int cameraId, int degrees) {
if (null == mCamera) {
try {
mCamera = Camera.open(cameraId);
mCamera.setDisplayOrientation(degrees);
} catch (Exception e) {
}
}
return mCamera;
}
Get the best preview size
1. Obtain all preview resolutions supported by the camera
// 获取相机支持的所有预览分辨率
List<Camera.Size> allSupportedSize =
mCamera.getParameters().getSupportedPreviewSizes();
2. Calculate the appropriate resolution for preview
This step is to obtain a maximum resolution size with the same resolution ratio as SurfaceView, so that the photo will not be deformed when previewing and taking pictures.
/**
* 获取适合的分辨率
*
* @param camera camera实例
* @param rate 预览尺寸长宽比
* @return 获取
*/
private Camera.Size getSupportedPreviewSize(Camera camera, int rate) {
Camera.Parameters camPara = camera.getParameters();
List<Camera.Size> allSupportedSize = camPara.getSupportedPreviewSizes();
for (Camera.Size tmpSize : allSupportedSize) {
if (tmpSize.width / tmpSize.height == rate) {
return tmpSize;
}
}
return null;
}
3. Perform camera preview
Camera preview is divided into three steps:
- Implement the callback of surfaceHolder
- Set the surfaceHolder as the display control of the camera
- Turn on camera preview
private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
@Override
public boolean isCreating() {
return false;
}
@Override
public void addCallback(Callback callback) {
}
@Override
public void removeCallback(Callback callback) {
}
@Override
public void setFixedSize(int width, int height) {
}
@Override
public void setSizeFromLayout() {
}
@Override
public void setFormat(int format) {
}
@Override
public void setType(int type) {
}
@Override
public void setKeepScreenOn(boolean screenOn) {
}
@Override
public Canvas lockCanvas() {
return null;
}
@Override
public Canvas lockCanvas(Rect dirty) {
return null;
}
@Override
public void unlockCanvasAndPost(Canvas canvas) {
}
@Override
public Surface getSurface() {
return null;
}
@Override
public Rect getSurfaceFrame() {
return null;
}
};
private void restartPreview(SurfaceHolder holder) {
if (camera != null) {
if (holder.getSurface() == null) {
return;
}
try {
camera.stopPreview();
} catch (Exception e) {
}
try {
// 将surfaceViewHolder设置为camera的显示控件
camera.setPreviewDisplay(holder);
// 开启相机预览
camera.startPreview();
if (listener != null) {
listener.onStartPreview();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. Take pictures
To take a picture, you only need to call camera.takePicture().