android.hardware.camera2使用指南

来源:互联网 发布:固定收益 知乎 编辑:程序博客网 时间:2024/06/05 13:31

API 21中将原来的camera API弃用转而推荐使用新增的camera2 API,这是一个大的动作,因为新API换了架构,让开发者用起来更难了。 
先来看看camera2包架构示意图: 
 
这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送Capture请求,而摄像头会返回CameraMetadata。这一切建立在一个叫作CameraCaptureSession的会话中。

下面是camera2包中的主要类: 
 
其中CameraManager是那个站在高处统管所有摄像投设备(CameraDevice)的管理者,而每个CameraDevice自己会负责建立CameraCaptureSession以及建立CaptureRequest。CameraCharacteristics是CameraDevice的属性描述类,非要做个对比的话,那么它与原来的CameraInfo有相似性。 
类图中有着三个重要的callback,虽然这增加了阅读代码的难度,但是你必须要习惯,因为这是新包的风格。其中CameraCaptureSession.CaptureCallback将处理预览和拍照图片的工作,需要重点对待。

这些类是如何相互配合的?下面是简单的流程图。 

我是用SurfaceView作为显示对象(当然还可以TextureView去显示,详见参考中的项目) 
核心代码如下:

        mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);        mSurfaceView = (SurfaceView)findViewById(R.id.surfaceview);        mSurfaceHolder = mSurfaceView.getHolder();        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {            @Override            public void surfaceCreated(SurfaceHolder holder) {                initCameraAndPreview();            }        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
    private void initCameraAndPreview() {        Log.d("linc","init camera and preview");        HandlerThread handlerThread = new HandlerThread("Camera2");        handlerThread.start();        mHandler = new Handler(handlerThread.getLooper());        try {            mCameraId = ""+CameraCharacteristics.LENS_FACING_FRONT;            mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(),                    ImageFormat.JPEG,/*maxImages*/7);            mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mHandler);            mCameraManager.openCamera(mCameraId, DeviceStateCallback, mHandler);        } catch (CameraAccessException e) {            Log.e("linc", "open camera failed." + e.getMessage());        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
private CameraDevice.StateCallback DeviceStateCallback = new CameraDevice.StateCallback() {        @Override        public void onOpened(CameraDevice camera) {            Log.d("linc","DeviceStateCallback:camera was opend.");            mCameraOpenCloseLock.release();            mCameraDevice = camera;            try {                createCameraCaptureSession();            } catch (CameraAccessException e) {                e.printStackTrace();            }        }    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
    private void createCameraCaptureSession() throws CameraAccessException {        Log.d("linc","createCameraCaptureSession");        mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);        mPreviewBuilder.addTarget(mSurfaceHolder.getSurface());        mState = STATE_PREVIEW;        mCameraDevice.createCaptureSession(                Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()),                mSessionPreviewStateCallback, mHandler);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new            CameraCaptureSession.StateCallback() {        @Override        public void onConfigured(CameraCaptureSession session) {            Log.d("linc","mSessionPreviewStateCallback onConfigured");            mSession = session;            try {                mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE,                        CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);                mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE,                        CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);                session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);            } catch (CameraAccessException e) {                e.printStackTrace();                Log.e("linc","set preview builder failed."+e.getMessage());            }        }    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback =            new CameraCaptureSession.CaptureCallback() {        @Override        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,                                       TotalCaptureResult result) {//            Log.d("linc","mSessionCaptureCallback, onCaptureCompleted");            mSession = session;            checkState(result);        }        @Override        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,                                        CaptureResult partialResult) {            Log.d("linc","mSessionCaptureCallback, onCaptureProgressed");            mSession = session;            checkState(partialResult);        }        private void checkState(CaptureResult result) {            switch (mState) {                case STATE_PREVIEW:                    // NOTHING                    break;                case STATE_WAITING_CAPTURE:                    int afState = result.get(CaptureResult.CONTROL_AF_STATE);                    if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||                            CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState                            || CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState                            || CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState) {                        //do something like save picture                    }                    break;            }        }    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

按下capture按钮:

    public void onCapture(View view) {        try {            Log.i("linc", "take picture");            mState = STATE_WAITING_CAPTURE;            mSession.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

测试用genemotion模拟器,直接调用笔记本的摄像头。 
配置图如下: 
 
demo界面如下图: 

源码: 
请参考github中的两个demo项目: 
https://github.com/pinguo-yuyidong/Camera2 
https://github.com/googlesamples/android-Camera2Basic

转载:http://blog.csdn.net/lincyang/article/details/45951225