美文网首页camera2
Android 使用Camera2写个简单的拍照小程序

Android 使用Camera2写个简单的拍照小程序

作者: 风二叽 | 来源:发表于2019-04-12 17:05 被阅读0次

    一.流程

    1.获取CameraManager

    2.通过CameraManager根据ID获取摄像头参数CameraCharacteristics,获取输出尺寸

    3.通过CameraManager开启摄像头,并在回调中获取到CameraDevice对象。

    4.通过CameraDevice对象创建CameraCaptureSession。

    5.构建CaptureRequest请求,分别有预览/拍照/录像三种模式

     6.通过CameraCaptureSession发起请求(capture方法只发一次, setRepeatingRequest方法会一直发)。

    7.在ImageReader的回调中处理拍照结果。

    二.各个流程代码

    1.获取CameraManager并获取摄像头参数

    2.用CameraManager开启摄像头,并在回调中构建预览请求,通过session发送请求

    开启摄像头 开启摄像头的回调 获取session并发起预览

    3.创建ImageReader的回调

    imageReader的回调

    4.构建拍照请求,并用session发起请求,拍照的数据在ImageReader的回调中处理,自己定义方法就行了

    发起拍照请求

    三.完整代码

    activity代码:

    package com.example.administrator.servicereceiver;

    import android.Manifest;

    import android.content.Context;

    import android.content.pm.PackageManager;

    import android.graphics.Bitmap;

    import android.graphics.BitmapFactory;

    import android.graphics.ImageFormat;

    import android.graphics.SurfaceTexture;

    import android.hardware.camera2.CameraAccessException;

    import android.hardware.camera2.CameraCaptureSession;

    import android.hardware.camera2.CameraCharacteristics;

    import android.hardware.camera2.CameraDevice;

    import android.hardware.camera2.CameraManager;

    import android.hardware.camera2.CameraMetadata;

    import android.hardware.camera2.CaptureRequest;

    import android.hardware.camera2.TotalCaptureResult;

    import android.hardware.camera2.params.StreamConfigurationMap;

    import android.media.Image;

    import android.media.ImageReader;

    import android.support.annotation.NonNull;

    import android.support.v4.app.ActivityCompat;

    import android.support.v7.app.AppCompatActivity;

    import android.os.Bundle;

    import android.util.Log;

    import android.util.Size;

    import android.util.SparseIntArray;

    import android.view.Surface;

    import android.view.TextureView;

    import android.view.View;

    import android.widget.ImageView;

    import android.widget.TextView;

    import java.nio.ByteBuffer;

    import java.util.Arrays;

    public class Camera2Activityextends AppCompatActivity {

    private TextureViewtextureView; //预览界面

        private ImageViewimageView;

        private TextViewcapture;

        private TextureView.SurfaceTextureListenersurfaceTextureListener;

        private CameraDevice.StateCallbackmStateCallback;//相机开启回调

    //摄像头设备,它有一系列参数(预览尺寸、拍照尺寸等),可以通过CameraManager的getCameraCharacteristics()方法获取。

    // 它的作用主要是创建CameraCaptureSession和CaptureRequest

        private CameraDevicemCameraDevice;

        private CameraManagercameraManager;//管理手机上的所有摄像头设备,它的作用主要是获取摄像头列表和打开指定的摄像头

        private SurfacemPreviewSurface;//预览Surface

        private SurfacemPhotoSurface;//拍照Surface

        private ImageReaderimageReader;

        private StringmCameraId;//相机id,区分前后置相机

        private SizemPreviewSize;//预览尺寸

    //    private Size captureSize;//成像尺寸

        private Bitmapbitmap;

        private CameraCaptureSessionmSession;//相机捕获会话,用于处理拍照和预览的工作

        private CaptureRequestmCaptureRequest;//捕获请求,定义输出缓冲区以及显示界面(TextureView或SurfaceView)等

        private CaptureRequest.BuildermCaptureRequestBuilder;

        private CameraCaptureSession.CaptureCallbackmSessionCaptureCallback;//相机捕获会话请求回调

        private static final SparseIntArrayORIENTATION =new SparseIntArray();

        static {

    ORIENTATION.append(Surface.ROTATION_0, 90);

            ORIENTATION.append(Surface.ROTATION_90, 0);

            ORIENTATION.append(Surface.ROTATION_180, 270);

            ORIENTATION.append(Surface.ROTATION_270, 180);

        }

    /**

    *  流程:

    *  1.获取CameraManager

    *  2.通过CameraManager根据ID获取摄像头参数CameraCharacteristics,获取输出尺寸

    *  3.通过CameraManager开启摄像头,并在回调中获取到CameraDevice对象。

    *  4.通过CameraDevice对象创建CameraCaptureSession。

    *  5.构建CaptureRequest请求,分别有预览/拍照/录像三种模式

    *  6.通过CameraCaptureSession发起请求(capture方法只发一次, setRepeatingRequest方法会一直发)。

    *  7.在ImageReader的回调中处理拍照结果。

    */

        @Override

        protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_camera2);

            findViews();

            initValues();

            setListeners();

        }

    private void findViews(){

    textureView = findViewById(R.id.textureView);

            imageView = findViewById(R.id.imageView);

            capture = findViewById(R.id.capture);

        }

    private void initValues(){

    //获取CameraManager

            cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

            initSurfaceTextureListener();

        }

    private void setListeners(){

    textureView.setSurfaceTextureListener(surfaceTextureListener);

            capture.setOnClickListener(new View.OnClickListener() {

    @Override

                public void onClick(View v) {

    takePhoto();

                }

    });

        }

    private void initSurfaceTextureListener(){

    surfaceTextureListener =new TextureView.SurfaceTextureListener() {

    @Override

                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

    openCamera(false);

                }

    @Override

                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override

                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {

    return false;

                }

    @Override

                public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    };

        }

    private CameraDevice.StateCallbackinitStateCallback(){

    if(mStateCallback ==null){

    mStateCallback =new CameraDevice.StateCallback() {

    @Override

                    public void onOpened(@NonNull CameraDevice camera) {

    mCameraDevice = camera;

                        openPreview();

                    }

    @Override

                    public void onDisconnected(@NonNull CameraDevice camera) {

    }

    @Override

                    public void onError(@NonNull CameraDevice camera, int error) {

    }

    };

            }

    return mStateCallback;

        }

    private SurfacegetmPreviewSurface(){

    if (mPreviewSurface ==null) {

    SurfaceTexture mSurfaceTexture =textureView.getSurfaceTexture();

                //设置TextureView的缓冲区大小

                mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

                //获取Surface显示预览数据

                mPreviewSurface =new Surface(mSurfaceTexture);

            }

    return mPreviewSurface;

        }

    private SurfacegetmPhotoSurface(){

    if (imageReader ==null) {

    imageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(), ImageFormat.JPEG, 2);

                imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {

    @Override

                    public void onImageAvailable(ImageReader reader) {

    getCaptureData(reader);

                    }

    },null);

                mPhotoSurface =imageReader.getSurface();

            }

    return mPhotoSurface;

        }

    private void closeCamera() {

    if (mSession !=null) {

    mSession.close();

                mSession =null;

            }

    if (mCameraDevice !=null) {

    mCameraDevice.close();

                mCameraDevice =null;

            }

    if (imageReader !=null) {

    imageReader.close();

                imageReader =null;

                mCaptureRequestBuilder =null;

            }

    }

    private void openCamera(boolean isFront){

    closeCamera();

            if(isFront){

    mCameraId = CameraCharacteristics.LENS_FACING_FRONT +"";

            }

    else {

    mCameraId = CameraCharacteristics.LENS_FACING_BACK +"";

            }

    setCameraData();

            try {

    if (checkPermission()) {

    //打开相机

                    cameraManager.openCamera(mCameraId, initStateCallback(), null);

                }

    }catch (CameraAccessException e) {

    e.printStackTrace();

            }

    }

    //设置相机参数

        private void setCameraData(){

    try {

    //获取相机的参数

                CameraCharacteristics characteristics =cameraManager.getCameraCharacteristics(mCameraId);

                //获取摄像头支持的所有输出格式和尺寸

                StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);//获取所有预览尺寸

                mPreviewSize = previewSizes[0];//获取预览尺寸

    //设置预览尺寸

                textureView.getSurfaceTexture().setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

            }catch (CameraAccessException e) {

    Log.getStackTraceString(e);

            }

    }

    //开启预览

        private void openPreview(){

    try {

    mCaptureRequestBuilder =mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);

                mCaptureRequestBuilder.addTarget(getmPreviewSurface()); //设置Surface作为预览数据的显示界面

                mCameraDevice.createCaptureSession(Arrays.asList(getmPreviewSurface(), getmPhotoSurface()),

                        new CameraCaptureSession.StateCallback() {//创建Session,需先完成画面呈现目标(此处为预览和拍照Surface)的初始化

                    @Override

                    public void onConfigured(@NonNull CameraCaptureSession session) {

    try {

    //构建预览请求,并发起请求

                            Log.e("","[发出预览请求]");

                            mSession = session;

                            mCaptureRequest =mCaptureRequestBuilder.build();

                            session.setRepeatingRequest(mCaptureRequest, getmSessionCaptureCallback(), null);

                        }catch (CameraAccessException e) {

    Log.e("",Log.getStackTraceString(e));

                        }

    }

    @Override

                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {

    session.close();

                    }

    }, null);

            }catch (CameraAccessException e) {

    Log.e("",Log.getStackTraceString(e));

            }

    }

    //获取拍照数据

        private void getCaptureData(ImageReader reader){

    Image image = reader.acquireLatestImage();

            ByteBuffer buffer = image.getPlanes()[0].getBuffer();

            byte[] data =new byte[buffer.remaining()];

            buffer.get(data);

            image.close();

            if (bitmap !=null) {

    bitmap.recycle();

                bitmap =null;

            }

    bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

            data =null;

            if (bitmap !=null) {

    showImage(bitmap);

            }

    Runtime.getRuntime().gc();

        }

    /**

    * 预览回调对象

        * @return

        */

        private CameraCaptureSession.CaptureCallbackgetmSessionCaptureCallback() {

    if (mSessionCaptureCallback ==null) {

    mSessionCaptureCallback =new CameraCaptureSession.CaptureCallback() {

    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {

    }

    };

            }

    return mSessionCaptureCallback;

        }

    //拍照

        private void takePhoto() {

    try {

    mCaptureRequestBuilder =mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

                mCaptureRequestBuilder.addTarget(imageReader.getSurface());

                mCaptureRequest =mCaptureRequestBuilder.build();

                Log.i(this.getClass().getName(), "发出请求");

                mSession.capture(mCaptureRequest, getmSessionCaptureCallback(), null);

            }catch (CameraAccessException e) {

    Log.e("",Log.getStackTraceString(e));

            }

    }

    //检查权限

        private boolean checkPermission(){

    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){

    return true;

            }

    else {

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 0);

    return false;

            }

    }

    private void showImage(Bitmap bitmap){

    imageView.setImageBitmap(bitmap);

        }

    @Override

        public void onDestroy(){

    super.onDestroy();

            closeCamera();

        }

    }

    界面布局:

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout 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"

        android:orientation="vertical"

        android:background="@color/colorBlank"

        tools:context=".Camera2Activity">

        android:id="@+id/textureView"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_weight="1"

        />

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:orientation="horizontal"

            android:layout_gravity="center_horizontal"

            android:gravity="center"

            >

                android:id="@+id/imageView"

                android:layout_width="50dp"

                android:layout_height="50dp"

                />

                android:id="@+id/capture"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:paddingTop="5sp"

                android:paddingBottom="5sp"

                android:paddingRight="20sp"

                android:paddingLeft="20sp"

                android:layout_marginLeft="30dp"

                android:textSize="16sp"

                android:textColor="@color/colorBlank"

                android:text="拍照"

                android:background="@color/colorSelect"

                />

    </LinearLayout>

    相关文章

      网友评论

        本文标题:Android 使用Camera2写个简单的拍照小程序

        本文链接:https://www.haomeiwen.com/subject/yuthwqtx.html