Camera2.0 拍照和录像

生搬硬套,代码纯属缝合,仅用于自己记忆

package com.szzysk.weibo.activity.chat;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
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.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.text.TextUtils;
import android.util.DisplayMetrics;
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 androidx.annotation.NonNull;

import com.szzysk.weibo.R;
import com.szzysk.weibo.base.BaseActivity;
import com.szzysk.weibo.utils.FileUtils;
import com.szzysk.weibo.utils.LogU;
import com.szzysk.weibo.utils.OnTwoTabDialogListener;
import com.szzysk.weibo.utils.Screen;
import com.szzysk.weibo.utils.TToast;
import com.szzysk.weibo.view.dialog.CameraDialog;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.Semaphore;

import butterknife.BindView;
import butterknife.ButterKnife;

public class CameraActivity extends BaseActivity {
    @BindView(R.id.sView)
    TextureView mTextureView;
    @BindView(R.id.mImage_camera)
    ImageView mImage_camera;
    @BindView(R.id.mImage_video)
    ImageView mImage_video;

    @BindView(R.id.mImage)
    ImageView mImage;
    @BindView(R.id.mImage_stop)
    ImageView mImage_stop;

    @BindView(R.id.mText_time)
    TextView mText_time;
    @BindView(R.id.mText_tip)
    TextView mText_tip;

    private CameraActivity cameraActivity;

    private boolean isRecording = true;
    private boolean isPicture = true;
    private MediaRecorder mMediaRecorder;
    private CameraCaptureSession mCaptureSession;
    private CameraCaptureSession mPhotoCaptureSession;

    private CameraDevice mCameraDevice;
    private String mCurrentSelectCamera;
    private String mFaceSelectCamera;
    private String mTempCamera;
    private CaptureRequest.Builder mPreviewBuilder;
    private CaptureRequest.Builder mCameraDevicePhotoCaptureRequest;

    private CameraManager mCameraManager;

    private int deviceWidth;
    private int deviceHeigh;


    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
    private static final SparseIntArray ORIENTATIONS_FACE = new SparseIntArray();

    private CameraCaptureSession.StateCallback mSessionStateCallback;
    private CameraDevice.StateCallback mCameraDeviceStateCallback;
    private CameraCaptureSession.CaptureCallback mCaptureCallback;

    static {// /为了使照片竖直显示
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
        ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    static {// /为了使照片竖直显示
        ORIENTATIONS_FACE.append(Surface.ROTATION_0, 270);
        ORIENTATIONS_FACE.append(Surface.ROTATION_90, 180);
        ORIENTATIONS_FACE.append(Surface.ROTATION_180, 90);
        ORIENTATIONS_FACE.append(Surface.ROTATION_270, 0);
    }

    private Semaphore mCameraOpenCloseLock = new Semaphore(1);

    private File file;
    private ImageReader mImageReader;

    private HandlerThread mBackgroundThread;

    private CaptureRequest mPreviewRequest;
    private int videoTime;
    private boolean isFace = false;
    private String randomImageFilePath;

    @Override
    protected int getContentLayout() {
        return R.layout.activity_camera;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        cameraActivity = this;
        ButterKnife.bind(this);
        Screen screen = new Screen();
        screen.fullScreen(this, true);

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); //因为我这里是将预览铺满屏幕,所以直接获取屏幕分辨率
        deviceWidth = displayMetrics.widthPixels;
        deviceHeigh = displayMetrics.heightPixels;
        LogU.d("getMatchingSize2: 屏幕密度宽度=" + deviceWidth + ", 屏幕密度高度=" + deviceHeigh);

        initChildHandler();
        initCaptureCallback();
        initCameraDeviceStateCallback();    //初始化(相机拍照)
        initMediaRecorder();
        mImage_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        mImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchCamera();
            }
        });
        mImage_camera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (isPicture) {
                    //    TToast.showToastCenter(CameraActivity.this, "拍照");
                    //  lockFocus();
                    Bitmap bitmap_get = mTextureView.getBitmap();
                    randomImageFilePath = FileUtils.getRandomImageFilePath(CameraActivity.this);
                    randomImageFilePath = FileUtils.saveFileByBitmap(CameraActivity.this, bitmap_get, randomImageFilePath).getAbsolutePath();
                    timeHandler.sendEmptyMessage(3);
                } else {
                    //   stopRecorder();
                }

            }
        });
        mImage_video.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LogU.d("isPicture=" + isPicture + ",isRecording=" + isRecording);
                if (!isPicture && isRecording) {
                    mText_time.setVisibility(View.VISIBLE);
                    TToast.showToastCenter(CameraActivity.this, "开始录像");
                    resetSession();
                    startRecorder();
                    timeHandler.sendEmptyMessage(1);
                    isRecording = false;
                } else if (!isPicture && !isRecording) {
                    TToast.showToastCenter(CameraActivity.this, "结束录像");
                    stopRecorder();
                }

            }
        });
        mImage_video.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (!isPicture && isRecording) {
                    isPicture = true;
                    initCameraDeviceStateCallback();
                    initTextureViewStateListener();     //切换拍照
                    mImage_video.setVisibility(View.GONE);
                    mImage_camera.setVisibility(View.VISIBLE);
                    mText_tip.setText("轻触拍照,长按切换录像");
                    mText_time.setVisibility(View.GONE);
                }
                return false;
            }
        });
        mImage_camera.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (isPicture) {
                    isPicture = false;

                    initStateCallback();
                    initCameraDeviceStateCallback();
                    initTextureViewStateListener();     //切换录像
                    mImage_video.setVisibility(View.VISIBLE);
                    mImage_camera.setVisibility(View.GONE);
                    mText_tip.setText("轻触录像,长按切换拍照");
                }

                return false;
            }
        });

    }

    public void switchCamera() {
        if (isFace) {
            mCurrentSelectCamera = mTempCamera;
            isFace = false;
        } else {
            mCurrentSelectCamera = mFaceSelectCamera;
            isFace = true;
        }
        closeCamera();
        initCameraDeviceStateCallback();
        initTextureViewStateListener();

    }

    TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
            LogU.d("onSurfaceTextureAvailable");
            initCameraManager();
            selectCamera();
            if (isPicture) {
                initImageReader(width, height);
            }
            openCamera();

        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
            //configureTransform(width, height);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture texture) {

        }
    };

    private void initImageReader(int width, int height) {
        mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG,/*maxImages*/7);
        mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mChildHandler);

    }

    private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            LogU.w("reader.hashCode()=" + reader.hashCode());
            if (isPicture && TextUtils.isEmpty(randomImageFilePath)) {
                randomImageFilePath = FileUtils.getRandomImageFilePath(CameraActivity.this);
                Runnable runnable = FileUtils.savePicture(reader.acquireNextImage(), new File(randomImageFilePath));
                mChildHandler.post(runnable);

                timeHandler.sendEmptyMessage(3);
            }
        }
    };


    /**
     * 初始化TextureView的纹理生成监听,只有纹理生成准备好了。我们才能去进行摄像头的初始化工作让TextureView接收摄像头预览画面
     */
    private void initTextureViewStateListener() {
        if (mTextureView.isAvailable()) {
            if (isPicture) {
                Size cameraSize = getMatchingSize2();
                initImageReader(cameraSize.getWidth(), cameraSize.getHeight());
            }
            openCamera();
        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }

    private Handler mChildHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            LogU.e("mChildHandler");
            return false;
        }
    });
    private Handler timeHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:

                    videoTime = 30;
                    mText_time.setText("00:" + videoTime);
                    timeHandler.sendEmptyMessageDelayed(2, 1000);
                    break;
                case 2:
                    videoTime = videoTime - 1;
                    mText_time.setText("00:" + videoTime);
                    if (videoTime == 0) {
                        stopRecorder();
                    } else {
                        timeHandler.sendEmptyMessageDelayed(2, 1000);
                    }

                    break;
                case 3:

                    CameraDialog cameraDialog = new CameraDialog(CameraActivity.this, randomImageFilePath, new OnTwoTabDialogListener() {
                        @Override
                        public void onButton() {
                            Intent intent = new Intent();
                            intent.putExtra("PhotoPath", randomImageFilePath);
                            intent.putExtra("result_type", 0);
                            setResult(RESULT_OK, intent);
                            finish();
                        }

                        @Override
                        public void onCancel() {

                            randomImageFilePath = null;
                            createCameraPreviewSession();

                            //   finish();
//                            if (null != mImageReader) {
//                                mImageReader.close();
//                                mImageReader = null;
//                            }
//                             //重新拍照
//                            initTextureViewStateListener();
//                            initCameraDeviceStateCallback();

                        }
                    });
                    cameraDialog.showDialog();
                    break;
            }
            return false;
        }
    });

    /**
     * 初始化子线程Handler,操作Camera2需要一个子线程的Handler
     */
    private void initChildHandler() {
        HandlerThread handlerThread = new HandlerThread("Camera2Demo");
        handlerThread.start();
        mChildHandler = new Handler(handlerThread.getLooper());
    }

    /**
     * 初始化MediaRecorder
     */
    private void initMediaRecorder() {
        mMediaRecorder = new MediaRecorder();
    }

    /**
     * 配置录制视频相关数据
     */
    private void configMediaRecorder() {
        try {
            file = new File(FileUtils.getRandomVideoMP4FilePath(this));

            //  File file = new File(getExternalCacheDir(), "demo.mp4");
            LogU.d("configMediaRecorder=" + file.getAbsolutePath());
            if (file.exists()) {
                file.delete();
            }
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频来源
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//设置视频来源
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置输出格式
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//设置音频编码格式,请注意这里使用默认,实际app项目需要考虑兼容问题,应该选择AAC
            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//设置视频编码格式,请注意这里使用默认,实际app项目需要考虑兼容问题,应该选择H264
            mMediaRecorder.setVideoEncodingBitRate(8 * 1024 * 1920);//设置比特率 一般是 1*分辨率 到 10*分辨率 之间波动。比特率越大视频越清晰但是视频文件也越大。
            mMediaRecorder.setVideoFrameRate(30);//设置帧数 选择 30即可, 过大帧数也会让视频文件更大当然也会更流畅,但是没有多少实际提升。人眼极限也就30帧了。
            Size size = getMatchingSize2();
            mMediaRecorder.setVideoSize(size.getWidth(), size.getHeight());
            if (isFace) {
                mMediaRecorder.setOrientationHint(270);
            } else {
                mMediaRecorder.setOrientationHint(90);
            }

            Surface surface = new Surface(mTextureView.getSurfaceTexture());
            mMediaRecorder.setPreviewDisplay(surface);
            mMediaRecorder.setOutputFile(file.getAbsolutePath());

            mMediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
            LogU.d("IOException=" + e.getLocalizedMessage());
        } catch (Exception e) {
            LogU.d("Exception=" + e.getLocalizedMessage());

        }


    }

    /**
     * 重新配置录制视频时的CameraCaptureSession
     */
    private void resetSession() {

        try {
            mCaptureSession.stopRepeating();//停止预览,准备切换到录制视频
            mCaptureSession.close();//关闭预览的会话,需要重新创建录制视频的会话
            mCaptureSession = null;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        configMediaRecorder();
        Size cameraSize = getMatchingSize2();
        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(), cameraSize.getHeight());
        Surface previewSurface = new Surface(surfaceTexture);
        Surface recorderSurface = mMediaRecorder.getSurface();//从获取录制视频需要的Surface
        try {
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);// 自动对焦
            mPreviewBuilder.addTarget(previewSurface);
            mPreviewBuilder.addTarget(recorderSurface);


            //请注意这里设置了Arrays.asList(previewSurface,recorderSurface) 2个Surface,很好理解录制视频也需要有画面预览,第一个是预览的Surface,第二个是录制视频使用的Surface
            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recorderSurface), mSessionStateCallback, mChildHandler);

        } catch (CameraAccessException e) {
            LogU.e("CameraAccessException=" + e.getLocalizedMessage());
        } catch (Exception e) {
            LogU.e("resetSession Exception=" + e.getLocalizedMessage());
        }

    }

    /**
     * 开始录制视频
     */
    private void startRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.start();
        }
    }

    /**
     * 暂停录制视频(暂停后视频文件会自动保存)
     */
    private void stopRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.stop();
            mMediaRecorder.release();
            if (timeHandler != null) {
                timeHandler.removeCallbacksAndMessages(null);
            }
            //   mMediaRecorder.reset();
            Intent intent = new Intent();
            intent.putExtra("VideoPath", file.getAbsolutePath());
            intent.putExtra("result_type", 1);
            setResult(RESULT_OK, intent);
            finish();
        }
    }

    /**
     * 初始化Camera2的相机管理,CameraManager用于获取摄像头分辨率,摄像头方向,摄像头id与打开摄像头的工作
     */
    private void initCameraManager() {
        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    }

    /**
     * 选择一颗我们需要使用的摄像头,主要是选择使用前摄还是后摄或者是外接摄像头
     */
    private void selectCamera() {
        if (mCameraManager == null) {
            LogU.d("selectCamera: CameraManager is null");
            return;
        }
        try {
            String[] cameraIdList = mCameraManager.getCameraIdList();   //获取当前设备的全部摄像头id集合
            if (cameraIdList.length == 0) {
                LogU.d("selectCamera: cameraIdList length is 0");
            }
            for (String cameraId : cameraIdList) { //遍历所有摄像头
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);//得到当前id的摄像头描述特征
                Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); //获取摄像头的方向特征信息

                if (facing == CameraCharacteristics.LENS_FACING_FRONT) {//这里选择了前摄像头
                    mFaceSelectCamera = cameraId;
                }
                if (facing == CameraCharacteristics.LENS_FACING_BACK) { //这里选择了后摄像头
                    mCurrentSelectCamera = cameraId;
                    mTempCamera = cameraId;
                }
            }

        } catch (CameraAccessException e) {
            LogU.e("CameraAccessException=" + e.getLocalizedMessage());
        }
    }

    private void initCameraDeviceStateCallback() {
        mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(@NonNull CameraDevice camera) {
                if (isPicture) {
                    LogU.d("摄像头被打开 ");
                    mCameraOpenCloseLock.release();
                    mCameraDevice = camera;
                    createCameraPreviewSession();

                } else {
                    LogU.d("录像头被打开 ");
                    //摄像头被打开
                    try {
                        mCameraDevice = camera;
                        Size cameraSize = getMatchingSize2();//计算获取需要的摄像头分辨率
                        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();//得到纹理
                        surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(), cameraSize.getHeight());
                        Surface previewSurface = new Surface(surfaceTexture);
                        mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                        mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                        mPreviewBuilder.addTarget(previewSurface);
                        //     为相机预览,创建一个CameraCaptureSession对象
                        mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), mSessionStateCallback, mChildHandler);//创建数据捕获会话,用于摄像头画面预览,这里需要等待mSessionStateCallback回调

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


            }


            @Override
            public void onDisconnected(CameraDevice cameraDevice) {
                if (isPicture) {                //摄像头断开
                    mCameraOpenCloseLock.release();
                    cameraDevice.close();
                    mCameraDevice = null;
                }

            }

            @Override
            public void onError(CameraDevice cameraDevice, int error) {
                if (isPicture) {                //异常
                    mCameraOpenCloseLock.release();
                    cameraDevice.close();
                    mCameraDevice = null;
                }
            }
        };
    }

    private void initStateCallback() {
        mSessionStateCallback = new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession session) {
                mCaptureSession = session;
                try {
                    //执行重复获取数据请求,等于一直获取数据呈现预览画面,mSessionCaptureCallback会返回此次操作的信息回调
                    mCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), mCaptureCallback, mChildHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                    LogU.e("CameraAccessException=" + e.getLocalizedMessage());
                }

            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                LogU.d("onConfigureFailed");
                //开启预览失败
            }
        };

    }

    private void initCaptureCallback() {
        mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
                super.onCaptureStarted(session, request, timestamp, frameNumber);
            }

            @Override
            public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
                super.onCaptureProgressed(session, request, partialResult);
                //      LogU.d("isPicture="+isPicture+",mState="+mState);
                if (isPicture) {
                    mPhotoCaptureSession = session;
                    checkState(partialResult);
                } else {
                    mCaptureSession = session;
                }
            }

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                if (isPicture) {
                    mPhotoCaptureSession = session;
                    checkState(result);
                } else {
                    mCaptureSession = session;
                }
            }

            @Override
            public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
                super.onCaptureFailed(session, request, failure);
                //开启预览失败
                //   LogU.e("onCaptureFailed");
            }
        };
    }

    private void checkState(CaptureResult result) {

        switch (mState) {
            case STATE_PREVIEW:
                // We have nothing to do when the camera preview is working normally.
                break;
            case STATE_WAITING_PRECAPTURE:
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                //  LogU.d("afState =" + afState);
                if (afState == null) {
                    captureStillPicture();
                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
                        || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState
                        || CaptureResult.CONTROL_AF_STATE_INACTIVE == afState) {

                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        captureStillPicture();
                    } else {
                        //runPrecaptureSequence();//视频拍摄
                        LogU.d("视频拍摄");
                    }
                }
                break;
        }
    }

    private void captureStillPicture() {
        try {
            if (null == mCameraDevice) {
                LogU.d("mCameraDevice=null");
                return;
            }

            final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(mImageReader.getSurface());//拍照时,是将mImageReader.getSurface()作为目标

            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            //  LogU.d("rotation=" + rotation);
            if (isFace) {
                captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS_FACE.get(rotation));
            } else {
                captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            }

            CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {

                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                               @NonNull CaptureRequest request,
                                               @NonNull TotalCaptureResult result) {
                    if (isPicture) {
                        unlockFocus();//恢复预览
                    }
                }
            };

            mPhotoCaptureSession.stopRepeating();
            mPhotoCaptureSession.abortCaptures();
            mPhotoCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private static final int STATE_PREVIEW = 1;
    private static final int STATE_WAITING_PRECAPTURE = 2;
    private int mState = STATE_PREVIEW;

    private void unlockFocus() {
        try {

            mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            mState = STATE_PREVIEW;
            mPhotoCaptureSession.setRepeatingRequest(mCameraDevicePhotoCaptureRequest.build(), mCaptureCallback, mChildHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void createCameraPreviewSession() {
        try {
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            Size matchingSize2 = getMatchingSize2();
            LogU.d("Width=" + mTextureView.getWidth() + ",Height=" + mTextureView.getHeight());
            texture.setDefaultBufferSize(matchingSize2.getWidth(), matchingSize2.getHeight());

            Surface surface = new Surface(texture);

            mCameraDevicePhotoCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mCameraDevicePhotoCaptureRequest.addTarget(surface);//预览时,是将Surface()作为目标
            mState = STATE_PREVIEW;
            Surface surface1 = mImageReader.getSurface();
            LogU.e("surface1=" + surface1.hashCode());
            mCameraDevice.createCaptureSession(Arrays.asList(surface, surface1),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {

                            if (mCameraDevice == null) {
                                LogU.d("null == mCameraDevice");
                                return;
                            }
                            mPhotoCaptureSession = cameraCaptureSession;
                            try {
                                mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                                mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                                mPreviewRequest = mCameraDevicePhotoCaptureRequest.build();
                                mPhotoCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mChildHandler);
                            } catch (Exception e) {

                                LogU.e("set preview builder failed." + e.getLocalizedMessage());
                            }
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                            LogU.e("Camera configuration Failed");
                        }
                    }, mChildHandler);
        } catch (CameraAccessException e) {

            LogU.e("CameraAccessException=" + e.getLocalizedMessage());
        }
    }

    /**
     * 打开摄像头,这里打开摄像头后,我们需要等待mCameraDeviceStateCallback的回调
     */
    @SuppressLint("MissingPermission")
    private void openCamera() {
        try {
            mCameraManager.openCamera(mCurrentSelectCamera, mCameraDeviceStateCallback, mChildHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
            LogU.e("openCamera=" + e.getLocalizedMessage());
        }
    }

    /**
     * 计算需要的使用的摄像头分辨率
     *
     * @return
     */
    private Size getMatchingSize2() {
        Size selectSize = null;
        try {
            CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCurrentSelectCamera);
            StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);

            /**
             * 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率,
             * 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况
             * ,但是循环越大后获取的分辨率就越不匹配
             */
            for (int j = 1; j < 41; j++) {
                for (int i = 0; i < sizes.length; i++) { //遍历所有Size
                    Size itemSize = sizes[i];
                    //  LogU.d("当前itemSize 宽=" + itemSize.getWidth() + "高=" + itemSize.getHeight());
                    //判断当前Size高度小于屏幕宽度+j*5  &&  判断当前Size高度大于屏幕宽度-j*5  &&  判断当前Size宽度小于当前屏幕高度
                    if (itemSize.getHeight() < (deviceWidth + j * 5) && itemSize.getHeight() > (deviceWidth - j * 5)) {
                        if (selectSize != null) { //如果之前已经找到一个匹配的宽度
                            if (Math.abs(deviceHeigh - itemSize.getWidth()) < Math.abs(deviceHeigh - selectSize.getWidth())) { //求绝对值算出最接近设备高度的尺寸
                                selectSize = itemSize;
                                continue;
                            }
                        } else {
                            selectSize = itemSize;
                        }

                    }
                }
                if (selectSize != null) { //如果不等于null 说明已经找到了 跳出循环
                    break;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        LogU.w("getMatchingSize2: 选择的分辨率宽度=" + selectSize.getWidth() + ",选择的分辨率高度=" + selectSize.getHeight());

        return selectSize;
    }

    private void lockFocus() {
        try {
            mCameraDevicePhotoCaptureRequest.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            //  mCaptureSession.capture(mPreviewBuilder.build(), mCaptureCallback, mChildHandler);
            if (isPicture) {
                mState = STATE_WAITING_PRECAPTURE;
                mPhotoCaptureSession.capture(mCameraDevicePhotoCaptureRequest.build(), mCaptureCallback, mChildHandler);
            }
        } catch (CameraAccessException e) {
            LogU.e("CameraAccessException=" + e.getLocalizedMessage());
        } catch (Exception e) {
            LogU.e("lockFocus Exception=" + e.getLocalizedMessage());
        }
    }

    private void closeCamera() {
        try {
            mCameraOpenCloseLock.acquire();
            if (null != mPhotoCaptureSession) {
                mPhotoCaptureSession.close();
                mPhotoCaptureSession = null;
            }
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            if (null != mImageReader) {
                mImageReader.close();
                mImageReader = null;
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
        } finally {
            mCameraOpenCloseLock.release();
        }
    }

    private void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mChildHandler = new Handler(mBackgroundThread.getLooper());
    }


    private void stopBackgroundThread() {
        if (mBackgroundThread != null) {
            mBackgroundThread.quitSafely();
            try {
                mBackgroundThread.join();
                mBackgroundThread = null;
                mChildHandler = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (isPicture) {
            startBackgroundThread();
            initTextureViewStateListener();
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (isPicture) {
            closeCamera();
            stopBackgroundThread();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaRecorder != null) {
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
        if (timeHandler != null) {
            timeHandler.removeCallbacksAndMessages(null);
        }
    }


}

你可能感兴趣的:(不用找系列,android)