Android开发之控制相机

来源:互联网 发布:fc2最新域名 chenghua 编辑:程序博客网 时间:2024/06/06 00:14

前言

如何通过使用Android框架所提供的API来直接控制相机硬件?

这篇博客将会讲解如何创建一个特殊的相机应用或将相机整合在我们的应用当中。

1.打开相机对象

获取一个 Camera 对象是直接控制相机的第一步。正如Android自带的相机程序一样,比较好的访问相机的方式是在onCreate()方法里面另起一个线程来打开相机。这种办法可以避免因为启动时间较长导致UI线程被阻塞。另外还有一种更好的方法:可以把打开相机的操作延迟到onResume()方法里面去执行,这样可以使得代码更容易重用,还能保持控制流程更为简单。

如果我们在执行Camera.open()方法的时候相机正在被另外一个应用使用,那么函数会抛出一个Exception,我们可以利用try语句块进行捕获:

    private boolean safeCameraOpen(int id) {        boolean qOpened = false;        try {            realeaseCameraAndPreview();            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 realeaseCameraAndPreview() {        mPreview.setCamera(null);        if (mCamera != null) {            mCamera.release();            mCamera = null;        }    }

自从API Level 9开始,相机框架可以支持多个相机。如果使用旧的API,在调用open()时不传入参数 ,那么我们会获取后置摄像头

2.创建相机预览界面

拍照通常需要向用户提供一个预览界面来显示待拍摄的事物。我们可以使用SurfaceView来展现照相机采集的图像。

2.1 Preview类

我们需要使用Preview类来显示预览界面。这个类需要实现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);    }...}

2.2 设置和启动Preview

一个Camera实例与它相关的Preview必须以特定的顺序来创建,其中Camera对象首先被创建。在下面的示例中,初始化Camera的动作被封装了起来,这样,无论用户想对Camera做什么样的改变,Camera.startPreview()都会被setCamera()调用。另外,Preview对象必须在surfaceChanged()这一回调方法里面重新启用(restart)。

        public void setCamera(Camera camera) {            if (mCamera == camera)                return;            stopPreviewAndFreeCamera();            mCamera = camera;            if (mCamera != null) {                List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();                mSupportedPreviewSize = localSizes;                requestLayout();                mCamera.setPreviewDisplay(mHolder);                // Important: Call startPreview() to start updating the preview                // surface. Preview must be started before you can take a picture.                mCamera.startPreview();            }        }

3.修改相机设置

相机设置可以改变拍照的方式,从缩放级别到曝光补偿等。下面的例子仅仅演示了如何改变预览大小:

@Override        public void surfaceChanged(SurfaceHolder holder, int format, int width,                int height) {            // 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();        }

4.设置预览方向

大多数相机程序会锁定预览为横屏状态,因为该方向是相机传感器的自然方向。当然这一设定并不会阻止我们去拍竖屏的照片,因为设备的方向信息会被记录在EXIF头中。setCameraDisplayOrientation()方法可以让你在不影响照片拍摄过程的情况下,改变预览的方向。然而,对于Android API Level 14及以下版本的系统,在改变方向之前,我们必须先停止预览,然后再去重启它。

5.拍摄照片

只要预览开始之后,可以使用Camera.takePicture()方法拍摄照片。我们可以创建Camera.PictureCallback与Camera.ShutterCallback对象并将他们传递到Camera.takePicture()中。

如果我们想要进行连拍,可以创建一个Camera.PreviewCallback并实现onPreviewFrame()方法。我们可以拍摄选中的预览帧,或是为调用takePicture()建立一个延迟。

6.重启Preview

在拍摄好图片后,我们必须在用户拍下一张图片之前重启预览。下面的示例使用快门按钮来实现重启。

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

7.停止预览并释放相机

当应用使用好相机后,我们有必要进行清理操作。特别地,我们必须释放Camera对象,不然的话可能会引起其他应用崩溃,包括我们自己应用的新实例。

那么何时应该停止预览并释放相机呢?在预览的Surface被摧毁之后,可以做停止预览与释放相机的操作。如下面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;    }}
0 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩哭脸后喝水呛着了怎么办 摔跤引起的脸部半边儿僵硬怎么办 老人受了刺激大笑不止是怎么办 想让父母陪着玩 没时间怎么办 开过光的百家锁东西别人碰了怎么办 兔兔助手描述文件变了存档怎么办 扣扣没有绑手机被盗了怎么办 我的扣扣被盗了好友也被删了怎么办 小孩不胖但脖子黑怎么办呢 小孩喜欢歪头斜眼看东西怎么办 苹果x屏幕截图发送后成文字怎么办 小朋友照相照出老太脸是怎么办 照相把脸照的很长怎么办 小猫咪下半身不能动不吃不喝怎么办 画个火柴人2主页面进不了怎么办? 火柴人联盟2的衣厨怎么办 偶尔犯了一次错误很自责怎么办 房间已经装修好但想加线条怎么办 自己的房间特别乱却不想收拾怎么办 素描中当阴影面正对着自己怎么办 相爱的俩个人却不能在一起怎么办 苹果手机爱思助手下不了东西怎么办 苹果手机在爱思助手刷坏了怎么办 美团外卖摔坏我的奶茶怎么办 米兔定位电话头像突然调换了怎么办 还在气头上时孩子就来撒娇了怎么办 老公把老婆微信屏蔽了老婆该怎么办 魅族手机有质量问题不给退款怎么办 屏幕点不动锁屏密码无法点怎么办 在嘴巴和鼻翼周围长痘该怎么办 小孩嘴巴被蚊虫咬的红肿怎么办 每次洗头都掉好多头发该怎么办 关于宝宝脾不好胃口却很好怎么办 高中生掉发严重怎么办该看什么科 脱头发如何治疗 掉头发厉害怎么办 头发上突然秃了一小块怎么办 全秃过后长出来白色头发怎么办 高三学生喜欢打球影响学习怎么办 高三学生受同学搔挠学习怎么办 烫完头发掉头发很厉害怎么办 烫头发后掉头发很厉害怎么办