android.hardware.camera2使用指南

来源:互联网 发布:mac u盘 200m 编辑:程序博客网 时间:2024/05/17 23:54

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去显示,详见参考中的项目)
核心代码如下:

<code class="hljs java has-numbering">        mCameraManager = (CameraManager) <span class="hljs-keyword">this</span>.getSystemService(Context.CAMERA_SERVICE);        mSurfaceView = (SurfaceView)findViewById(R.id.surfaceview);        mSurfaceHolder = mSurfaceView.getHolder();        mSurfaceHolder.addCallback(<span class="hljs-keyword">new</span> SurfaceHolder.Callback() {            <span class="hljs-annotation">@Override</span>            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">surfaceCreated</span>(SurfaceHolder holder) {                initCameraAndPreview();            }        });</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>
<code class="hljs avrasm has-numbering">    private void initCameraAndPreview() {        Log<span class="hljs-preprocessor">.d</span>(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"init camera and preview"</span>)<span class="hljs-comment">;</span>        HandlerThread handlerThread = new HandlerThread(<span class="hljs-string">"Camera2"</span>)<span class="hljs-comment">;</span>        handlerThread<span class="hljs-preprocessor">.start</span>()<span class="hljs-comment">;</span>        mHandler = new Handler(handlerThread<span class="hljs-preprocessor">.getLooper</span>())<span class="hljs-comment">;</span>        try {            mCameraId = <span class="hljs-string">""</span>+CameraCharacteristics<span class="hljs-preprocessor">.LENS</span>_FACING_FRONT<span class="hljs-comment">;</span>            mImageReader = ImageReader<span class="hljs-preprocessor">.newInstance</span>(mSurfaceView<span class="hljs-preprocessor">.getWidth</span>(), mSurfaceView<span class="hljs-preprocessor">.getHeight</span>(),                    ImageFormat<span class="hljs-preprocessor">.JPEG</span>,<span class="hljs-comment">/*maxImages*/</span><span class="hljs-number">7</span>)<span class="hljs-comment">;</span>            mImageReader<span class="hljs-preprocessor">.setOnImageAvailableListener</span>(mOnImageAvailableListener, mHandler)<span class="hljs-comment">;</span>            mCameraManager<span class="hljs-preprocessor">.openCamera</span>(mCameraId, DeviceStateCallback, mHandler)<span class="hljs-comment">;</span>        } catch (CameraAccessException e) {            Log<span class="hljs-preprocessor">.e</span>(<span class="hljs-string">"linc"</span>, <span class="hljs-string">"open camera failed."</span> + e<span class="hljs-preprocessor">.getMessage</span>())<span class="hljs-comment">;</span>        }    }</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li></ul>
<code class="hljs java has-numbering"><span class="hljs-keyword">private</span> CameraDevice.StateCallback DeviceStateCallback = <span class="hljs-keyword">new</span> CameraDevice.StateCallback() {        <span class="hljs-annotation">@Override</span>        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onOpened</span>(CameraDevice camera) {            Log.d(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"DeviceStateCallback:camera was opend."</span>);            mCameraOpenCloseLock.release();            mCameraDevice = camera;            <span class="hljs-keyword">try</span> {                createCameraCaptureSession();            } <span class="hljs-keyword">catch</span> (CameraAccessException e) {                e.printStackTrace();            }        }    };</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>
<code class="hljs avrasm has-numbering">    private void createCameraCaptureSession() throws CameraAccessException {        Log<span class="hljs-preprocessor">.d</span>(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"createCameraCaptureSession"</span>)<span class="hljs-comment">;</span>        mPreviewBuilder = mCameraDevice<span class="hljs-preprocessor">.createCaptureRequest</span>(CameraDevice<span class="hljs-preprocessor">.TEMPLATE</span>_PREVIEW)<span class="hljs-comment">;</span>        mPreviewBuilder<span class="hljs-preprocessor">.addTarget</span>(mSurfaceHolder<span class="hljs-preprocessor">.getSurface</span>())<span class="hljs-comment">;</span>        mState = STATE_PREVIEW<span class="hljs-comment">;</span>        mCameraDevice<span class="hljs-preprocessor">.createCaptureSession</span>(                Arrays<span class="hljs-preprocessor">.asList</span>(mSurfaceHolder<span class="hljs-preprocessor">.getSurface</span>(), mImageReader<span class="hljs-preprocessor">.getSurface</span>()),                mSessionPreviewStateCallback, mHandler)<span class="hljs-comment">;</span>    }</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>
<code class="hljs avrasm has-numbering">private CameraCaptureSession<span class="hljs-preprocessor">.StateCallback</span> mSessionPreviewStateCallback = new            CameraCaptureSession<span class="hljs-preprocessor">.StateCallback</span>() {        @Override        public void onConfigured(CameraCaptureSession session) {            Log<span class="hljs-preprocessor">.d</span>(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"mSessionPreviewStateCallback onConfigured"</span>)<span class="hljs-comment">;</span>            mSession = session<span class="hljs-comment">;</span>            try {                mPreviewBuilder<span class="hljs-preprocessor">.set</span>(CaptureRequest<span class="hljs-preprocessor">.CONTROL</span>_AF_MODE,                        CaptureRequest<span class="hljs-preprocessor">.CONTROL</span>_AF_MODE_CONTINUOUS_PICTURE)<span class="hljs-comment">;</span>                mPreviewBuilder<span class="hljs-preprocessor">.set</span>(CaptureRequest<span class="hljs-preprocessor">.CONTROL</span>_AE_MODE,                        CaptureRequest<span class="hljs-preprocessor">.CONTROL</span>_AE_MODE_ON_AUTO_FLASH)<span class="hljs-comment">;</span>                session<span class="hljs-preprocessor">.setRepeatingRequest</span>(mPreviewBuilder<span class="hljs-preprocessor">.build</span>(), mSessionCaptureCallback, mHandler)<span class="hljs-comment">;</span>            } catch (CameraAccessException e) {                e<span class="hljs-preprocessor">.printStackTrace</span>()<span class="hljs-comment">;</span>                Log<span class="hljs-preprocessor">.e</span>(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"set preview builder failed."</span>+e<span class="hljs-preprocessor">.getMessage</span>())<span class="hljs-comment">;</span>            }        }    }<span class="hljs-comment">;</span></code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>
<code class="hljs java has-numbering"><span class="hljs-keyword">private</span> CameraCaptureSession.CaptureCallback mSessionCaptureCallback =            <span class="hljs-keyword">new</span> CameraCaptureSession.CaptureCallback() {        <span class="hljs-annotation">@Override</span>        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCaptureCompleted</span>(CameraCaptureSession session, CaptureRequest request,                                       TotalCaptureResult result) {<span class="hljs-comment">//            Log.d("linc","mSessionCaptureCallback, onCaptureCompleted");</span>            mSession = session;            checkState(result);        }        <span class="hljs-annotation">@Override</span>        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCaptureProgressed</span>(CameraCaptureSession session, CaptureRequest request,                                        CaptureResult partialResult) {            Log.d(<span class="hljs-string">"linc"</span>,<span class="hljs-string">"mSessionCaptureCallback, onCaptureProgressed"</span>);            mSession = session;            checkState(partialResult);        }        <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">checkState</span>(CaptureResult result) {            <span class="hljs-keyword">switch</span> (mState) {                <span class="hljs-keyword">case</span> STATE_PREVIEW:                    <span class="hljs-comment">// NOTHING</span>                    <span class="hljs-keyword">break</span>;                <span class="hljs-keyword">case</span> STATE_WAITING_CAPTURE:                    <span class="hljs-keyword">int</span> afState = result.get(CaptureResult.CONTROL_AF_STATE);                    <span class="hljs-keyword">if</span> (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) {                        <span class="hljs-comment">//do something like save picture</span>                    }                    <span class="hljs-keyword">break</span>;            }        }    };</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li></ul>

按下capture按钮:

<code class="hljs cs has-numbering">    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCapture</span>(View view) {        <span class="hljs-keyword">try</span> {            Log.i(<span class="hljs-string">"linc"</span>, <span class="hljs-string">"take picture"</span>);            mState = STATE_WAITING_CAPTURE;            mSession.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);        } <span class="hljs-keyword">catch</span> (CameraAccessException e) {            e.printStackTrace();        }    }</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

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

demo界面如下图:

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

0 0
原创粉丝点击