欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 编程开发之camera2

程序员文章站 2022-04-11 22:05:15
Android 编程开发之camera2。 布局只用到了SurfaceView跟Button。有的手机黑屏,需要给SurfaceViewHolder设置FixedSize。...

Android 编程开发之camera2。

Android 编程开发之camera2
布局只用到了SurfaceView跟Button。有的手机黑屏,需要给SurfaceViewHolder设置FixedSize。

public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private SurfaceView mCameraSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    //相机相关代码,三个必须的
    private CameraManager mCameraManager;
    private CameraDevice mCameraDevice;
    private CameraCaptureSession mCameraCaptureSession;
    //阻止相机关闭前退出app
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
    //摄像头id  0:后摄像头 1:前摄像头
    private static final String mCameraId = "" + CameraCharacteristics.LENS_FACING_FRONT;
    //opencamera方法中需要ImageReader和handler
    private ImageReader mImageReader;
    private Handler mHandler;
    private Size previewsize;
    private ImageReader.OnImageAvailableListener mImageAvailableListenter = new ImageReader.OnImageAvailableListener() {
        @SuppressLint("NewApi")
        @Override
        public void onImageAvailable(ImageReader reader) {
            mCameraDevice.close();
            //这里获取到图片数据
           ……

        }
    };

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    ///为了使照片竖直显示
    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);
    }

    /**
     * Max preview width that is guaranteed by Camera2 API
     */
    private static final int MAX_PREVIEW_WIDTH = 1920;

    /**
     * Max preview height that is guaranteed by Camera2 API
     */
    private static final int MAX_PREVIEW_HEIGHT = 1080;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        initView();
        initSurfaceView();
    }

    private void initView() {
        mCameraSurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
        mFrameIv = (ImageView) findViewById(R.id.frame_imageview);
        mTakePhotoBt = (Button) findViewById(R.id.takephoto_bt);
        mFocusView = findViewById(R.id.focus_index);

    }

    private void initSurfaceView() {
        mCameraSurfaceView.setBackgroundColor(TRIM_MEMORY_BACKGROUND);
        mSurfaceHolder = mCameraSurfaceView.getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
        mSurfaceHolder.addCallback(this);
    }


    @Override
    protected void onResume() {
        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
//这里可以设置也可以不设置,使用过程中发现有的手机不设置这个时会出现黑屏现象
        mSurfaceHolder.setFixedSize(800, 600);
        super.onResume();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

 //不设置holder的Fixedsize时设置initCamera2(mCameraSurfaceView.getWidth(),mCameraSurfaceView.getHeight());
            initCamera2(800, 600);         

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @SuppressLint("NewApi")
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCameraDevice != null) {
            mCameraDevice.close();
        }
    }

    @SuppressLint("NewApi")
    private void initCamera2(int width, int height) {
        if (checkCameraPermission()) {
            try {
                String camerId = mCameraManager.getCameraIdList()[0];
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(camerId);
                StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                previewsize = map.getOutputSizes(SurfaceTexture.class)[0];
                HandlerThread handlerthread = new HandlerThread("Camera2");
                handlerthread.start();
                mHandler = new Handler(handlerthread.getLooper());
                mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG,  /*maxImages*/2);
                mImageReader.setOnImageAvailableListener(mImageAvailableListenter, mHandler);
                mCameraManager.openCamera(mCameraId, mCameraDeviceCallBack, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        } else {
            finish();
            return;
        }

    }

    private boolean checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(getApplicationContext(),
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(getApplicationContext(), "没有相机权限", Toast.LENGTH_LONG).show();
            return false;
        } else {
            return true;
        }
    }


    @SuppressLint("NewApi")
    private CameraDevice.StateCallback mCameraDeviceCallBack = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            try {
                //当相机被打开,该方法将被回调,因此再这里进行相机预览设置
                mCameraOpenCloseLock.release();
                mCameraDevice = camera;
                //开启预览
                createCameraCaptureSession();
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCameraOpenCloseLock.release();
            if (mCameraDevice != null) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
        }


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

        }
    };
    private CaptureRequest.Builder mCaptureRequestBuilder;

    @SuppressLint("NewApi")//开启预览
    private void createCameraCaptureSession() throws CameraAccessException {
        //创建预览需要的CaptureRequest.Builder
        mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        //添加surface为CaptureRequest.Builder的目标
        mCaptureRequestBuilder.addTarget(mSurfaceHolder.getSurface());
        //创建CameraCaptureSession该对象负责管理处理预览请求和拍照请求
        mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(),
                mImageReader.getSurface()), mSessionPreviewStateCallback, mHandler);
    }

    @SuppressLint("NewApi")
    private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            try {
                //摄像头已经准备好,开始显示预览
                mCameraCaptureSession = session;
                //自动对焦
                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                //打开闪光灯
//                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                //显示预览
                CaptureRequest previewRequest = mCaptureRequestBuilder.build();
                mCameraCaptureSession.setRepeatingRequest(previewRequest, null, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Log.e("Camera2", "相机预览失败");
        }
    };
//


    public void takePicture(View view) {
        takePic();
    }

    @SuppressLint("NewApi")
    public void takePic() {
        if (mCameraDevice == null) return;
        // 创建拍照需要的CaptureRequest.Builder
        try {
            // 将imageReader的surface作为CaptureRequest.Builder的目标
            mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
            // 自动对焦
            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 自动曝光
            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            // 获取手机方向
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            // 根据设备方向计算设置照片的方向
            mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            //拍照
            CaptureRequest mCaptureRequest = mCaptureRequestBuilder.build();
            mCameraCaptureSession.capture(mCaptureRequest, null, mHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

}