【Android:构建相机应用】
文章目录
一、检测和访问相机 - 创建用于检查设备是否配有相机和请求访问权限的代码。
如果您的应用没有明确要求相机使用清单声明,那么您应该检查一下相机在运行时是否可用。如需执行此项检查,请使用 PackageManager.hasSystemFeature()
方法,如以下示例代码所示:
/** 检查此设备是否有摄像头*/
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
//这个设备有摄像头,返回true
return true;
} else {
// 否则返回false
return false;
}
}
Android 设备可拥有多个摄像头,例如,一个用于摄影的后置摄像头和一个用于视频通话的前置摄像头。在 Android 2.3(API 级别 9)及更高版本中,您可以使用 Camera.getNumberOfCameras()
方法查看设备上的可用摄像头数量。
二、访问相机
如果您已经确定运行您应用的设备配有相机,那么必须通过获取 Camera
实例请求该相机的访问权限(除非您正在使用 intent
访问相机)。
如需访问主摄像头,请使用 Camera.open()
方法并确保捕获任何异常,如以下代码所示:
/** 获取摄影机对象实例的安全方法 */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // 尝试获取摄影机实例
}
catch (Exception e){
// 摄像头不可用(正在使用或不存在)
}
return c; // 如果相机不可用,则返回null
}
注意:在使用 Camera.open()
时,请务必检查是否存在异常。如果相机正在使用中或不存在,未能检查异常会导致系统关闭您的应用。
三、检查相机功能
获取相机的访问权限后,您可以使用 Camera.getParameters()
方法获取有关相机功能的详细信息,还可以检查返回的 Camera.Parameters
对象,以获取受支持的功能。在使用 API 级别 9 或更高级别时,请使用 Camera.getCameraInfo()
确定设备的摄像头是前置还是后置,以及图片的方向。
四、 创建预览类 :创建可扩展 SurfaceView
并实现 SurfaceHolder
接口的相机预览类。此类会预览相机拍摄的实时图片。
为了高效地拍摄照片或视频,用户必须能够看到进入相机视野的画面。相机预览类是一个 SurfaceView
,可显示从相机传入的实时图片数据,以便用户取景并拍摄照片或视频。
以下示例代码演示了如何创建可包含在 View
布局中的基本相机预览类。此类会实现 SurfaceHolder.Callback
,以捕获用于创建和销毁视图的回调事件,这些是分配相机预览输入所需的事件。
/** 基本的相机预览*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// 安装SurfaceHolder。回拨以便我们收到通知
// 下面被创建和销毁
mHolder = getHolder();
mHolder.addCallback(this);
// 已弃用的设置,但在3.0之前的Android版本上是必需的
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// surface已经创建,现在告诉相机在哪里绘制预览。
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// 注意在活动中释放相机预览。
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// 如果预览可以更改或旋转,请在此处处理这些事件。
// 在调整预览大小或重新设置预览格式之前,请确保停止预览。
if (mHolder.getSurface() == null){
// 预览曲面不存在,返回
return;