Android学习笔记 --- Camera

前面已经对camera的API和相关知识进行了描述,下面我们就camera的实例进行讲解。

android使用camera开发拍照应用最基本的流程:

  • 使用open(int cameraId)获取camera实例。
  • 为camera实例设置预览类,他是一个SurfaceHolder对象,通过setPreviewDisplay(SurfaceHolder)设置。
  • 调用startPreview()开始camera实例的预览
  • 调用takePicture()方法进行拍照,其中可以通过Camera.PictureCallback()回调获得拍摄的Image数据。
  • 当拍摄完成后,需要调用stopPreview()停止预览,并使用release()释放camera占用的资源。

以上步骤是必不可少的过程,camera没有公开的构造函数,只能通过open()方法获取camera实例,并且设置一个surfaceHolder预览类,如果这一步未实现的,将无法使用camera。待camera使用完成后,必须使用release()释放camera资源。下面便就实例进行详细的讲解。

以下实例分为这几步:

  • 系统权限配置
  • 相机布局
  • 相机预览设置
  • 相机拍照

系统权限配置

// 相机权限
<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" />

相机布局

<?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>
 

相机预览设置

相机预览设置需要先获取相机以及相机预览尺寸,然后在将相机预览画面通过SurfaceView显示出来。

获取相机

/**
* 获取相机实例
* 
* @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;
}
 

获取最佳预览尺寸

1、获取相机支持的所有预览分辨率

// 获取相机支持的所有预览分辨率
 List<Camera.Size> allSupportedSize = 
            mCamera.getParameters().getSupportedPreviewSizes();

2、计算合适的分辨率进行预览

这一步就是获取一个与SurfaceView同等分辨率比例的一个最大分辨率尺寸,只有这样在预览和拍照时相片才不会变形。

    /**
     * 获取适合的分辨率
     *
     * @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、进行相机预览

相机预览分为三步:

  • 实现surfaceHolder的回调
  • 将surfaceHolder设置为camera的显示控件
  • 开启相机预览
 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、拍照

拍照只需要调用camera.takePicture()即可。

猜你喜欢

转载自blog.csdn.net/xiaowang_lj/article/details/131822890