private CaptureRequest.Builder mPreviewBuilder; // 声明一个预览请求构建器对象
    private CaptureRequest.Builder mCaptureBuilder; // 声明一个拍照请求构建器对象



一、打开相机

// 从系统服务中获取相机管理器
        CameraManager cm = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
		// 获取可用相机特性
            CameraCharacteristics cc = cm.getCameraCharacteristics(cameraId);
	CameraDevice.StateCallback mDeviceStateCallback = new CameraDevice.StateCallback()
	 // 开启摄像头,在StateCallback 回调onOpened 之后,初始化CameraDevice mCameraDevice并 开启预览,
     cm.openCamera(cameraId, mDeviceStateCallback, mHandler);


二、开启预览

// 获取纹理视图的表面纹理
        SurfaceTexture texture = mPlayerView.getSurfaceTexture();
        // 设置表面纹理的默认缓存尺寸:即预览尺寸
        texture.setDefaultBufferSize(mPreViewSize.getWidth(), mPreViewSize.getHeight());
        // 创建一个该表面纹理的表面对象
        mSurface = new Surface(texture);
		//创建预览请求构建器对象,通过该对象可以设置曝光、对焦、预览方向等
		mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

	//创建ImageReader,并设置拍照数据监听
	mImageReader = ImageReader.newInstance(Config.SHOOT_PIC_WIDTH,
                        Config.SHOOT_PIC_HEIGHT, ImageFormat.JPEG, 1);
	mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                    @Override
                    public void onImageAvailable(ImageReader reader) {
                        //获取最新的image
                        Image image = reader.acquireLatestImage();
						//用完后面一定要调用close,否则crash 且不会有持续的预览回调,
						image.close();
		}, null);
	 // 把纹理视图添加到预览目标,不添加没法预览
     mPreviewBuilder.addTarget(mSurface);
	 //添加这句可以获取实时预览数据回调,一般ImageReader 设置格式为ImageFormat.YUV_420_888 处理实时yuv预览帧
	 //比如做算法处理等
	 mPreviewBuilder.addTarget(mImageReader.getSurface());		// 创建一个相片捕获会话。此时需要两个surface(texureview和ImageReader)该对象负责管理处理预览请求和拍照请求
    mCameraDevice.createCaptureSession(Arrays.asList(mSurface, mImageReader.getSurface()),
                        mSessionStateCallback, mHandler);
	//在CameraCaptureSession 配置成功回调后调用
	CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback(){
	 @Override
        public void onConfigured(CameraCaptureSession session) {
		           mCameraSession = session;
                    // 设置连拍请求。此时预览画面
                    mCameraSession.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler);
		    }
        }

三、拍照

//创建拍照请求构建器对象,该对象需要设置ImageReader的surface对象,设置图片方向等
     mCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
	 mCaptureBuilder.addTarget(mImageReader.getSurface());

	 //执行拍照,CaptureCallback只是处理拍照状态回调,拍照数据从上面的ImageReader回调获取
	 //如果拍照的时候是停止预览的,再拍照回调完成后需要在调用mCameraSession.setRepeatingRequest
	 mCameraSession.capture(mCaptureBuilder.build(), mCaptureCallback, mHandler);
	 CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession
            .CaptureCallback()


四、其他 预览拍照做镜像处理
现在cameraid只有是前摄才会做镜像处理,但是车机中舱内摄像头 cameraid 不是前摄的,
但是也要做前摄的预览拍照效果,该怎么办
1.预览界面做镜像

//如果需要将预览界面镜像处理,可以对texture view做处理 镜像翻转处理。
	ArchTaskExecutor.getInstance().executeOnMainThread(() -> {
        mPlayerView.setScaleX(-1f);
      });


2.imagereader 拍照 做镜像处理

mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
             //处理拍照回调,保存拍照数据
            Bitmap bitmap = getByteFromReader(reader);
             Log.i(TAG, "onImageAvailable() null != bitmap?" + (null != bitmap));
             Bitmap bitmap2 = flipBitmap(bitmap);
             if (null != bitmap2) {
               doCaptureAfterGetImage(bitmap2);
             }
        }
     }, null);

    /**
     * 对图片做镜像处理
     *
     * @param bitmap
     */
    private Bitmap flipBitmap(Bitmap bitmap) {
        if (null == bitmap) {
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Matrix m = new Matrix();
        m.postScale(-1, 1);   //镜像水平翻转
        //m.postScale(1, -1);   //镜像垂直翻转
        //m.postRotate(-90);  //旋转-90度
        Bitmap new2 = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, true);
        bitmap.recycle();
        return new2;
    }