Android camera2 使用方法

2021-10-28  本文已影响0人  飞不起的小鸟
    private TextureView textureview;
    private Camera2 camera;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
             textureview = findViewById(R.id.textureview);

//进入这个页面之前要申请相机权限
             camera = new Camera2(textureview, this, new Camera.OnCameraListener() {
                  @Override
                   public void onCall(Bitmap bitmap) {
                          //拍照的bitmap
                    }
              });

            findViewById(R.id.btn).setOnClickListener(new OnClickLimitListener() {
                    @Override
                    public void click(View v) {
                        Log.d(TAG, "click: 拍照");
                        camera.takePic();
                    }
        });
   }

import android.Manifest;
import android.app.Activity;
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.CaptureFailure;
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.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class Camera {

    private Activity mActivity;
    private TextureView mTextureView;
    private HandlerThread handlerThread;
    private CameraManager mCameraManager;
    private ImageReader mImageReader;
    private CameraDevice mCameraDevice;
    private CameraCaptureSession mCameraCaptureSession;
    private String mCameraId;
    private CameraCharacteristics mCameraCharacteristics;
    private int mCameraSensorOrientation;
    private boolean canTakePic;
    private Handler mCameraHandler;
    private Size mPreviewSize;
    private Size mSavePicSize;
    private ImageReader.OnImageAvailableListener onImageAvailableListener;
    private CameraCaptureSession.CaptureCallback mCaptureCallBack;

    public Camera(TextureView textureView, Activity activity, OnCameraListener listener) {
        mTextureView = textureView;
        mActivity = activity;
        handlerThread = new HandlerThread("CameraThread");
        handlerThread.start();
        mCameraHandler = new Handler(handlerThread.getLooper());

        mPreviewSize = new Size(720, 1280);
        mSavePicSize = new Size(720, 1280);

        onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = reader.acquireNextImage();
                ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
                byte[] byteArray = new byte[byteBuffer.remaining()];
                byteBuffer.get(byteArray);
                image.close();

                Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
                listener.onCall(bitmap);
            }
        };
        mCaptureCallBack = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                canTakePic = true;
            }
        };

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
                initInfo();
            }

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

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
                release();
                return true;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {

            }
        });

    }

    public void release() {
        if (mCameraCaptureSession != null) {
            mCameraCaptureSession.close();
            mCameraCaptureSession = null;
        }
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
        if (mImageReader != null) {
            mImageReader.close();
            mImageReader = null;
        }
    }

    private void initInfo() {
        try {
            mCameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
            String[] cameraIdList = mCameraManager.getCameraIdList();
            if (cameraIdList == null || cameraIdList.length == 0) {
                Toast.makeText(mActivity, "没有可用相机", Toast.LENGTH_SHORT).show();
                return;
            }

            for (int i = 0; i < cameraIdList.length; i++) {
                String id = cameraIdList[i];
                CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(id);
                Integer integer = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
                if (integer == CameraCharacteristics.LENS_FACING_BACK ) {
                    mCameraId = id;
                    mCameraCharacteristics = cameraCharacteristics;
                }
            }

            mCameraSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            StreamConfigurationMap configurationMap = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if (configurationMap != null) {
                Size[] savePicSize = configurationMap.getOutputSizes(ImageFormat.JPEG);
                Size[] previewSize = configurationMap.getOutputSizes(SurfaceTexture.class);

                int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
                boolean exchange = exchangeWidthAndHeight(rotation, mCameraSensorOrientation);


                mSavePicSize = getBestSize(
                        exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
                        exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
                        exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
                        exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
                        Arrays.asList(savePicSize));

                mPreviewSize = getBestSize(
                        exchange ? mPreviewSize.getHeight() : mPreviewSize.getWidth(),
                        exchange ? mPreviewSize.getWidth() : mPreviewSize.getHeight(),
                        exchange ? mTextureView.getHeight() : mTextureView.getWidth(),
                        exchange ? mTextureView.getWidth() : mTextureView.getHeight(),
                        Arrays.asList(previewSize));


                mTextureView.getSurfaceTexture().setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
                mImageReader = ImageReader.newInstance(mSavePicSize.getWidth(), mSavePicSize.getHeight(), ImageFormat.JPEG, 1);
                mImageReader.setOnImageAvailableListener(onImageAvailableListener, mCameraHandler);
                openCamera();
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void openCamera() {

        if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(mActivity, "没有相机权限!", Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            mCameraManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    mCameraDevice = camera;
                    createCaptureSession(camera);
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                }
            }, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void createCaptureSession(CameraDevice cameraDevice) {
        try {
            CaptureRequest.Builder captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            Surface surface = new Surface(mTextureView.getSurfaceTexture());
            captureRequest.addTarget(surface);
            captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

            cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigureFailed(CameraCaptureSession session) {
                    Toast.makeText(mActivity, "开启预览会话失败!", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onConfigured(CameraCaptureSession session) {
                    mCameraCaptureSession = session;
                    try {
                        session.setRepeatingRequest(captureRequest.build(), mCaptureCallBack, mCameraHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

            }, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private boolean exchangeWidthAndHeight(int displayRotation, int sensorOrientation) {
        boolean exchange = false;
        if (displayRotation == Surface.ROTATION_0 || displayRotation == Surface.ROTATION_180) {
            if (sensorOrientation == 90 || sensorOrientation == 270) {
                exchange = true;
            } else if (sensorOrientation == 0 || sensorOrientation == 180) {
                exchange = true;
            }
        }
        return exchange;
    }

    private Size getBestSize(int targetWidth, int targetHeight, int maxWidth, int maxHeight, List<Size> sizeList) {
        List<Size> bigEnough = new ArrayList<>();
        List<Size> notBigEnough = new ArrayList<>();

        for (Size size : sizeList) {
            if (size.getWidth() <= maxWidth && size.getHeight() <= maxHeight && size.getWidth() == size.getHeight() * targetWidth / targetHeight) {
                if (size.getWidth() >= targetWidth && size.getHeight() >= targetHeight)
                    bigEnough.add(size);
                else {
                    notBigEnough.add(size);
                }
            }
        }
        if (bigEnough.size() > 0) {
            return Collections.min(bigEnough, new CompareSizesByArea());
        } else if (notBigEnough.size() > 0) {
            return Collections.max(notBigEnough, new CompareSizesByArea());
        }
        return sizeList.get(0);
    }

    /**
     * 拍照
     */
    public void takePic() {
        if (mCameraDevice == null || !mTextureView.isAvailable() || !canTakePic) {
            return;
        }

        if (mCameraDevice != null) {
            try {
                CaptureRequest.Builder captureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                captureRequest.addTarget(mImageReader.getSurface());
                captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                captureRequest.set(CaptureRequest.JPEG_ORIENTATION, mCameraSensorOrientation);
                mCameraCaptureSession.capture(captureRequest.build(), null, mCameraHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
                Toast.makeText(mActivity, "拍照异常!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    class CompareSizesByArea implements Comparator<Size> {
        @Override
        public int compare(Size size1, Size size2) {
            return java.lang.Long.signum(
                    size1.getWidth() * size1.getHeight() -
                            size2.getWidth() * size2.getHeight());
        }
    }

    public interface OnCameraListener {
        void onCall(Bitmap bitmap);
    }
}
上一篇下一篇

猜你喜欢

热点阅读