构建一个Camera应用程序
某些开发可能想要在他们的应用中定制Camera的用户界面,或者要提供一些特殊的功能。创建定制化的Activity比使用Intent需要更多的代码,但它能够给你的户提供更好的体验。
以下是创建定制化的Camera界面的一般步骤:
1. 检查和访问Camera:创建代码来检查Camera和所申请访问的存在性;
2. 创建一个预览类:继承SurfaceView来创建一个Camera的预览类,并实现SurfaceHolder接口。这个类用来预览来之Camera的实施图像。
3. 构建一个预览布局:一旦有了Camera预览类,就可以把这个预览类和你想要的用户界面控制结合在一起来创建一个视图布局。
4. 针对采集建立监听:把监听器与响应用户动作(如按下按钮)的界面控制连接到一起来启动图像或视频的采集。
5. 采集和保存文件:针对真正采集的图片或视频,以及输出的保存来编写代码。
6. 释放Camera:使用Camera之后,你的应用程序必须释放Camera,以便其他应用程序能够使用。
Camera硬件是一个必须要认真管理的共享资源,因此你的应用程序在使用它时,不能跟其他应用程序发生冲突。下文将讨论如何检查Camera硬件、如何申请对Camera的访问,如何采集图片和视频,以及在应用使用完成后如何释放Camera。
警告:在应用程序使用完Camera时,要记住通过调用Camera.release()方法来释放Camera对象。如果你的应用程序没有正确的释放Camera,所有的后续的视图对Camera的访问,包括你自己的应用程序,都会失败,并可能到你的或其他的应用程序关闭。
检查Camera硬件
如果你的应用程序没有使用清单特别的声明要使用Camera,那么就应该在运行时检查Camera是否有效。使用PackageManager.hasSystemFeature()方法,来执行这个检查,如下例代码所示:
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
Android设备能够有多个Camera,例如用于摄影的背面Camera和用于视频会话的前面Camera。Android2.3(API Level9)以后的版本允许你使用Camera.getNumberOfCameras()方法来检查设备上可用的Camera的数量。
访问Camera
如果你已经判断在应用程序所运行的设备上有Camera,你必须获取通过Camera实例才能申请访问它(除非使用Intent来访问Camera)。
使用Camera.open()方法来访问主Camera,并确保要捕获任何异常,如下例代码所示:
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
警告:在使用Camera.open()时,要始终检查异常。如果没有检查Camera是否被使用或是否存在,会导致你的应用程序被系统关闭。
在运行Android2.3(API Level9)以上的设备上,你能够使用Camera.open(int)方法来访问指定的Camera。上面的示例代码访问的是第一个Camera,也就是多个Camera的设备上背面的那个Camera。
检查Camera功能
一旦获得了访问Camera的权限,就可以使用Camera.getParameters()方法来获取更多的有关Camera能力的信息,这个方法返回一个Camera.Parameters对象。在使用API Level9以上的版本时,使用Camera.getCameraInfo()方法来判断Camera是在设备的前面还是后面,以及图像的方向。
创建一个预览类
对用户有效的拍照或录像,必须是在设备的Camera上能够看到。Camera预览类是一个SurfaceView类,它能够实时的显示来自Camera的图像数据,因此用户能够取景和采集图片或视频。
下例的示例代码演示了如何创建能够被包含到View布局中的基本的Camera预览类。为了捕获创建和销毁View的回调事件,这个类实现了SurfaceHolder.Callback接口,用于跟Camera的预览输入相匹配:
/** A basic Camera preview class */
publicclassCameraPreviewextendsSurfaceViewimplementsSurfaceHolder.Callback{
privateSurfaceHolder mHolder;
privateCamera mCamera;
publicCameraPreview(Context context,Camera camera){
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
publicvoid surfaceCreated(SurfaceHolder holder){
// The Surface has been created, now tell the camera where to draw the preview.
try{
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}catch(IOException e){
Log.d(TAG,"Error setting camera preview: "+ e.getMessage());
}
}
publicvoid surfaceDestroyed(SurfaceHolder holder){
// empty. Take care of releasing the Camera preview in your activity.
}
publicvoid surfaceChanged(SurfaceHolder holder,int format,int w,int h){
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if(mHolder.getSurface()==null){
// preview surface does not exist
return;
}
// stop preview before making changes
try{
mCamera.stopPreview();
}catch(Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}catch(Exception e){
Log.d(TAG,"Error starting camera preview: "+ e.getMessage());
}
}
}
如果你要给你Camera预览窗口设置一个特定的尺寸,可以像上面注释中标注的那样,设置surfaceChanged()方法。在设置预览尺寸的时候,必须使用来自getSupportedPreviewSizes()方法的值,在setPreviewSize()方法中不能使用随意的值。