【Android Developers Training】 50. 控制相机
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。
原文链接:http://developer.android.com/training/camera/cameradirect.html
在这节课中,我们讨论如何直接通过框架内的API来控制相机硬件。
直接控制一个相机硬件需要的代码,比通过已存在的相机应用拍摄照片和视频所需要的代码要多。然而,如果你希望构建一个特制的相机应用,或者需要将一些东西整合入你的应用界面,那么这节课将会教授你如何去做。
一). 打开一个相机对象
要直接控制相机,首先应当获得一个相机(Camera)对象的实例。就像Android自己的相机应用所做的,推荐的访问相机的方法是在onCreate()方法中,通过一个独立的线程来启动。这个方法的优点在于访问相机需要一定的时间,这就导致如果在UI线程例访问相机,可能会造成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 Level 9之后,相机框架能够支持多个相机。如果你使用过去的API,并且调用了无传递参数的open()方法,你会得到第一个后置摄像头。
二). 创建相机预览
拍摄照片通常需要让你的用户可以在按下快门键之前看见一个实时预览界面。要这样做,一可以使用SurfaceView来绘制相机预览,显示传感器元件捕捉到的实时画面。
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);
}
...
}
Preview类必须在激活的相机预览启动之前传递给Camera对象,这方面知识将在下一节展开。
设置并启动预览
一个相机实例和与它相关联的相机预览必须以一个特定的顺序创建,相机对象在先。在下面的代码片段中,初始化相机的操作已经封装好了,所以我们可以看到Camera.startPreview()在setCamera()方法中被调用,不管何时用户做了什么事情来改变当前激活的摄像头。预览界面必须在preview类中的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()方法可以让你再不影响照片是如何拍摄的情况下改变预览的方向。然而,在Android API Level 14之前,你必须在改变方向之前停止你的相机预览,然后重新启动它。
五). 拍摄照片
一旦相机预览启动了,就可以通过Camera.takePicture()方法来拍摄照片。你可以创建Camera.PictureCallback和Camera.ShutterCallback对象,并将它们传递给Camera.takePicture()。
如果你希望连续抓拍图像,你可以创建一个实现了onPreviewFrame()的Camera.PreviewCallback。在这两件事情之间,你可以值捕获选中的预览框,或者设置一个调用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();
}
七). 停止相机预览并且释放相机
一旦你的应用完成了相机的拍摄,那么久到了释放资源的时间了。尤其要注意的是你要释放相机对象,不然的话你可能会导致其它应用的崩溃,这也包括你自己的应用。
那么什么时候应该停止预览并释放相机呢?当你的预览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;
}
}
中这堂课的前半部分,上述步骤也是“setCamera()”方法的一部分,所以初始化一个相机一般都始于停止相机预览。
【Android Developers Training】 50. 控制相机的更多相关文章
- 【Android Developers Training】 65. 应用投影和相机视图
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 44. 控制你应用的音量和播放
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 45. 控制音频焦点
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 47. 序言:拍摄照片
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 83. 实现高效网络访问来优化下载
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 64. 绘制形状
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 61. 序言:使用OpenGL ES显示图像
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 25. 保存文件
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 108. 使用模拟定位进行测试
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
随机推荐
- Windows 2008 R2下 如何简单使用IIS来配置PHP网站
虽然PHP网站配置一般大多数人可能会联想到用Apache+php+mysql来配置,但是呢,如果是为了安全性考虑或者是说是为了便捷高效快速的完成工作,那么Apache+php+mysql这个配置工作就 ...
- 点击Input框弹出日期选项
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 计算facebook sdk需要的key hashes
1. 下载openssl,在C盘创建openssl文件夹,解压下载的zip到openssl文件夹. 2. 找到debug.keystore. windows下在C:\Users\用户名\.androi ...
- 【转】c++ new操作符的重载
基本概念: 1. 操作符重载:C++支持对某个操作符赋予不同的语义 2. new操作符:申请内存,调用构造函数 关于c++ new操作符的重载 你知道c++ 的new 操作符和operator new ...
- MyBatis源码解读(4)——SqlSession(上)
在上一篇博客中提到MyBatis是如何实现代理类MapperProxy,并抛出了一个问题--是怎么执行一个具体的sql语句的,在文末中提到了MapperMethod的execute采用命令模式来判断是 ...
- 【JAVAWEB学习笔记】06_jQuery基础
接05的学习笔记. 四.使用JQ完成省市二级联动 1.需求分析 使用jquery完成省市二级联动 2.技术分析 2.1数组的遍历操作 方式一: $(function(){ // 全选/ 全不选 $(& ...
- 关于jQuery插件imgAreaSelect基础讲解
关于ImgAreaSelect, 是一jQuery插件,它支持用户通过鼠标拖曳选择图片的一部分,如图片拖曳.图片编辑等~~来具体看一下 1.先下载imgAreaSelect插件 下载地址: 英文:h ...
- asp.net已流的方式下载文件
string filePath = context.Server.MapPath("~/" + uploadFolder+"/"+file_name);//路径 ...
- 日志组件一:Log4j
log4j是Apache的一个开源项目,陪伴了我们多年,但是现在已经不更新了.官网原文如下: Log4j 1.x has been widely adopted and used in many ap ...
- laravel5.2之logout注销账号无效
问题描述:laravel5.2的框架,使用框架auth用户认证后,进行账号注销退出的时候,无法实现. 只有清除浏览器缓存,才能实现账号退出. 解决办法: 改变路由 Route::get('auth/l ...