美文网首页
Android camera2 使用方法

Android camera2 使用方法

作者: 飞不起的小鸟 | 来源:发表于2021-10-28 15: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);
        }
    }
    

    相关文章

      网友评论

          本文标题:Android camera2 使用方法

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