Android官方开发文档Training系列课程中文版:调用相机之控制相机-阿里云开发者社区

开发者社区> sahadev> 正文

Android官方开发文档Training系列课程中文版:调用相机之控制相机

简介: 原文地址:http://android.xsoftlab.net/training/camera/cameradirect.html 在这节课,我们会讨论如何使用Android框架API来直接控制相机硬件。
+关注继续查看

原文地址:http://android.xsoftlab.net/training/camera/cameradirect.html

在这节课,我们会讨论如何使用Android框架API来直接控制相机硬件。

直接控制设备的相机拍照或者摄像的代码远比通过其他相机应用来完成要多得多。然而,如果你想构建一个专业的相机应用或者在APP的UI中完全集成相机的话,这节课展示了如何去做。

开启相机对象

直接控制相机的第一步就是获得Camera对象的实例。和Android自身的相机应用相同,推荐访问相机的方式就是在独立的线程打开Camera,这种方式是应对阻塞UI线程的一个好的解决方法。在更加基础化的实现当中,开启相机这一步操作可以推迟到onResume()方法中执行,这样可以促使代码重用并且保持简单的控制流。

如果相机已经正在被其它应用所使用,那么调用Camera.open()方法会抛出一个异常,所以我们需要使用try控制块包裹住它:

private boolean safeCameraOpen(int id) {
    boolean qOpened = false;

    try {
        releaseCameraAndPreview();
        mCamera = Camera.open(id);
        qOpened = (mCamera != null);
    } catch (Exception e) {
        Log.e(getString(R.string.app_name), "failed to open Camera");
        e.printStackTrace();
    }
    return qOpened;    
}
private void releaseCameraAndPreview() {
    mPreview.setCamera(null);
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

从API 9开始,相机框架支持多个相机。如果你使用的是过去的API,然后调用了没有参数的open()方法,那么你会获得后置面板的相机。

创建相机预览

拍照通常需要可以使用户能看到目标的预览图。你可以使用SurfaceView来绘制相机传感器捕获到的图像。

预览类

为了可以显示预览,你需要预览类。预览需要一个android.view.SurfaceHolder.Callback接口的实现,它被用来从相机硬件给应用传递图像数据。

class Preview extends ViewGroup implements SurfaceHolder.Callback {
    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;
    Preview(Context context) {
        super(context);
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
...
}

在开始预览之前,必须将预览对象传递给Camera对象,就像下面部分展示的那样。

设置并开始预览

相机实例的创建于相关预览对象创建必须是以指定顺序进行的,从相机对象开始。在下面的代码中,实例化相机对象的过程被封装起来了,所以Camera.startPreview()是可以通过setCamera()调用的,每当用户做了什么事情使相机发生了改变。预览也必须在预览类的surfaceChanged()回调方法重新启动。

public void setCamera(Camera camera) {
    if (mCamera == camera) { return; }

    stopPreviewAndFreeCamera();

    mCamera = camera;

    if (mCamera != null) {
        List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedPreviewSizes = localSizes;
        requestLayout();

        try {
            mCamera.setPreviewDisplay(mHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Important: Call startPreview() to start updating the preview
        // surface. Preview must be started before you can take a picture.
        mCamera.startPreview();
    }
}

修改相机设置

相机设置可以改变相机拍照的方式,从缩放等级到曝光补偿等等。下面的示例只是更改了预览的大小;请查看相机应用的源代码获取更多可能。

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);
    // Important: Call startPreview() to start updating the preview surface.
    // Preview must be started before you can take a picture.
    mCamera.startPreview();
}

设置预览方向

大多数的相机应用将展示锁定在了水平方向,因为这是相机传感器的自然方向。这个设置并不能阻止你在垂直方向上拍摄,因为相机的方向会被记录到EXIF的头部。setCameraDisplayOrientation()方法允许你改变如何展示预览,而不受图像记录方向的影响。然而,在API14之前,在改变方向之前必须停止预览,然后在重新启动它。

拍照

一旦预览启动后,可以使用Camera.takePicture()方法来拍一张照片。你可以创建Camera.PictureCallback对象和Camera.ShutterCallback对象然后将它们传递给Camera.takePicture()方法。

重启预览

在拍了一张照片之后,你必须在用户拍另一张照片之前重新启动预览。在这个例子中,通过重写快门按钮来完成重启。

@Override
public void onClick(View v) {
    switch(mPreviewState) {
    case K_STATE_FROZEN:
        mCamera.startPreview();
        mPreviewState = K_STATE_PREVIEW;
        break;
    default:
        mCamera.takePicture( null, rawCallback, null);
        mPreviewState = K_STATE_BUSY;
    } // switch
    shutterBtnConfig();
}

停止预览并且释放相机

一旦你的程序不再需要使用相机,这时就需要执行清理工作。尤其是你需要释放相机对象,否则会使其它程序面临崩溃的风险,包括你自己程序中新的实例。

何时应该停止预览并释放相机呢?好吧,当预览界面被销毁的时候便是停止预览并释放相机的最佳时机,就像下面Preview类中显示的那样:

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();
    }
}
/**
 * When this function returns, mCamera will be null.
 */
private void stopPreviewAndFreeCamera() {
    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();

        // Important: Call release() to release the camera for use by other
        // applications. Applications should release the camera immediately
        // during onPause() and re-open() it during onResume()).
        mCamera.release();

        mCamera = null;
    }
}

在上面的课程中,这段程序也是setCamera()方法的一部分,所以实例化一个相机总是从停止这段预览开始的。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【Elastic Engineering】Elasticsearch 简介
Elasticsearch 是一个非常强大的搜索引擎。
9 0
一文快速搞定Redis_数据类型及JavaApi操作
大家好,我是**ChinaManor**,直译过来就是中国码农的意思,我希望自己能成为国家复兴道路的铺路人,大数据领域的耕耘者,平凡但不甘于平庸的人。
9 0
计算机基础2 | 学习笔记
快速学习计算机基础2。
11 0
【Elastic Engineering】Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
13 0
【Elastic Engineering】Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
3 0
Vue 集成腾讯地图基础api Demo集合(基础地图引入与展示模块,地址逆解析,3D/2D切换 ,位置服务,mark标记)
Vue 集成腾讯地图基础api Demo集合(基础地图引入与展示模块,地址逆解析,3D/2D切换 ,位置服务,mark标记)
7 0
安卓平板体验Java开发,还能白嫖一年阿里无影云!真香
阿里无影云早有耳闻,前两天看朋友发体验照片,可能是程序员天生爱折腾的特性又发挥作用了,自己也没能忍住,赶快下载体验了一把,没想到“很香”。我体验了浏览器端、Windows 客户端和安卓平板端,下面就来聊聊使用的过程和使用体验。内含一年免费无影云的白嫖方法,千万别错过哦~
31 0
计算机基础3 | 学习笔记
快速学习计算机基础3。
10 0
架构修炼之道 | 一个传统网关系统有几种 “死” 法(上)
架构修炼之道 | 一个传统网关系统有几种 “死” 法(上)
6 0
架构修炼之道 | 一个传统网关系统有几种 “死” 法(下)
架构修炼之道 | 一个传统网关系统有几种 “死” 法(下)
6 0
+关注
sahadev
移动开发方向专家
183
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载