Android相机开发指南:直接控制相机硬件

Android相机开发指南:直接控制相机硬件

android-training-course-in-chinese Android官方培训课程中文版 android-training-course-in-chinese 项目地址: https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese

在Android应用开发中,相机功能是非常重要且常用的模块。本文将深入讲解如何通过Android框架API直接控制相机硬件,实现自定义相机功能。

相机控制基础

直接控制相机相比调用系统相机应用要复杂得多,但能提供更灵活的定制能力。我们需要掌握以下几个核心概念:

  1. 相机实例管理:获取和释放Camera对象
  2. 预览界面:显示相机实时画面
  3. 参数配置:调整相机各项设置
  4. 拍照流程:实现拍照功能
  5. 资源释放:合理管理相机资源

获取相机实例

获取Camera实例是控制相机的第一步。最佳实践是在Activity的onCreate()方法中开启单独线程操作相机,避免阻塞UI线程。

private boolean safeCameraOpen(int id) {
    boolean isOpened = false;
    try {
        releaseCameraAndPreview();
        mCamera = Camera.open(id);  // 获取指定摄像头实例
        isOpened = (mCamera != null);
    } catch (Exception e) {
        Log.e(TAG, "相机打开失败");
        e.printStackTrace();
    }
    return isOpened;
}

注意:

  • 从API 9开始支持多摄像头,不传参数默认使用后置摄像头
  • 必须处理异常情况,防止其他应用占用相机时崩溃

创建预览界面

相机预览需要使用SurfaceView来显示实时画面。我们需要创建一个实现SurfaceHolder.Callback接口的Preview类:

class Preview extends ViewGroup implements SurfaceHolder.Callback {
    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;
    
    Preview(Context context) {
        super(context);
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);
        
        // 设置SurfaceHolder回调
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    ...
}

预览流程控制

相机实例与预览界面需要按特定顺序初始化:

  1. 先创建Camera实例
  2. 将Camera实例与Preview关联
  3. 启动预览
public void setCamera(Camera camera) {
    if (mCamera == camera) return;
    
    stopPreviewAndFreeCamera();  // 先停止现有预览
    
    mCamera = camera;
    
    if (mCamera != null) {
        // 获取支持的预览尺寸
        List<Size> sizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedPreviewSizes = sizes;
        requestLayout();
        
        try {
            mCamera.setPreviewDisplay(mHolder);  // 设置预览显示
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        mCamera.startPreview();  // 必须启动预览才能拍照
    }
}

相机参数配置

我们可以通过Camera.Parameters调整相机设置:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);  // 应用参数设置
    mCamera.startPreview();  // 重启预览使设置生效
}

常见可配置参数包括:

  • 预览尺寸
  • 图片尺寸
  • 对焦模式
  • 闪光灯模式
  • 白平衡
  • 曝光补偿等

方向处理

相机预览默认使用横屏方向,这是传感器自然方向。我们可以通过setDisplayOrientation()调整预览方向而不影响拍照:

public static void setCameraDisplayOrientation(Activity activity,
        int cameraId, Camera camera) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    
    int rotation = activity.getWindowManager().getDefaultDisplay()
            .getRotation();
    int degrees = 0;
    
    switch (rotation) {
        case Surface.ROTATION_0: degrees = 0; break;
        case Surface.ROTATION_90: degrees = 90; break;
        case Surface.ROTATION_180: degrees = 180; break;
        case Surface.ROTATION_270: degrees = 270; break;
    }
    
    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // 补偿镜像
    } else {
        result = (info.orientation - degrees + 360) % 360;
    }
    
    camera.setDisplayOrientation(result);
}

拍照实现

启动预览后,可以通过takePicture()方法拍照:

mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);

三个回调参数分别处理:

  1. ShutterCallback:快门声音触发时调用
  2. PictureCallback:原始图像数据可用时调用
  3. PictureCallback:JPEG图像数据可用时调用

拍照完成后必须重启预览才能继续拍照:

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

资源释放

相机是共享资源,必须及时释放:

private void stopPreviewAndFreeCamera() {
    if (mCamera != null) {
        mCamera.stopPreview();  // 停止预览
        mCamera.release();     // 释放相机资源
        mCamera = null;
    }
}

最佳实践是在Activity的onPause()中释放相机,在onResume()中重新获取。

总结

直接控制相机硬件需要处理较多细节,但提供了最大的灵活性。关键点包括:

  1. 合理管理相机实例生命周期
  2. 正确实现预览界面
  3. 妥善处理各种回调
  4. 及时释放资源

掌握这些技术后,开发者可以创建功能强大、界面独特的相机应用,满足各种专业拍摄需求。

android-training-course-in-chinese Android官方培训课程中文版 android-training-course-in-chinese 项目地址: https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邱晋力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值