当前位置:首页 > 技术 > 正文内容

Android 基于 Camera1 API 实现视频采集与画面预览

访客 技术 2026年6月15日 1

Camera1 API 概述

在 Android 系统中,android.hardware.Camera(通常称为 Camera1)是早期用于控制设备摄像头硬件的核心类。尽管自 API 21 起官方已将其标记为废弃并推荐使用 Camera2,但在许多遗留项目或特定兼容性场景中,Camera1 依然被广泛使用。它主要负责配置相机参数、管理预览流、捕获静态图像以及获取视频编码帧。

权限声明与动态申请

调用摄像头硬件前,必须在 AndroidManifest.xml 中声明相机权限:

<uses-permission android:name="android.permission.CAMERA" />

对于 Android 6.0(API 23)及以上版本,还需要在运行时动态申请权限。以下是优化后的权限请求逻辑:

private static final int REQ_CODE_PERMISSIONS = 1001;
private final String[] requiredPermissions = {
    Manifest.permission.CAMERA,
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
};

private void verifyAndRequestPermissions() {
    List<String> missingPermissions = new ArrayList<>();
    
    for (String perm : requiredPermissions) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            missingPermissions.add(perm);
        }
    }
    
    if (!missingPermissions.isEmpty()) {
        ActivityCompat.requestPermissions(this, 
            missingPermissions.toArray(new String[0]), REQ_CODE_PERMISSIONS);
    }
}

Camera1 核心工作流程

使用 Camera1 进行视频采集和预览的标准生命周期如下:

  1. 通过 Camera.open(int) 实例化相机对象并连接指定硬件。
  2. 调用 getParameters() 获取当前相机的配置参数。
  3. 修改配置后,通过 setParameters(Camera.Parameters) 应用新设置。
  4. 使用 setDisplayOrientation(int) 调整预览画面的旋转角度。
  5. 调用 setPreviewDisplay(SurfaceHolder) 将相机预览流绑定到 UI 表面。
  6. 执行 startPreview() 开启预览,这是进行拍照或录像的前置条件。
  7. 如需拍照,可调用 takePicture() 触发异步图像捕获(注意:拍照后预览会自动停止)。
  8. 调用 stopPreview() 停止预览流的渲染。
  9. 在 Activity 销毁或暂停时,务必调用 release() 释放相机资源,防止内存泄漏和硬件占用。

线程安全提示:Camera1 并非线程安全类,其所有操作应在同一个事件线程(通常是主线程)中执行。耗时的操作(如对焦、拍照)会通过回调异步返回结果。

预览与采集代码实现

下面展示如何结合 SurfaceView 实现相机的初始化、预览开启与资源释放。代码对变量命名和结构进行了重构,以提升可读性与模块化程度:

public class CameraPreviewManager implements SurfaceHolder.Callback {
    private Camera deviceCamera;
    private SurfaceHolder displayHolder;
    private boolean isPreviewing = false;

    public CameraPreviewManager(SurfaceView targetSurfaceView) {
        this.displayHolder = targetSurfaceView.getHolder();
        this.displayHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        initializeAndStartPreview();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // Surface 尺寸变化时的处理逻辑
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCameraResources();
    }

    private void initializeAndStartPreview() {
        try {
            deviceCamera = Camera.open();
            Camera.Parameters config = deviceCamera.getParameters();
            
            // 设置预览数据格式为 NV21
            config.setPreviewFormat(ImageFormat.NV21);
            deviceCamera.setParameters(config);
            
            // 绑定 Surface 并调整预览方向
            deviceCamera.setPreviewDisplay(displayHolder);
            deviceCamera.setDisplayOrientation(90);
            
            // 设置预览回调以获取视频帧数据
            deviceCamera.setPreviewCallback((data, camera) -> {
                // 在此处处理采集到的 NV21 视频帧数据
            });
            
            deviceCamera.startPreview();
            isPreviewing = true;
        } catch (IOException e) {
            Log.e("CameraManager", "预览启动失败", e);
        }
    }

    public void releaseCameraResources() {
        if (deviceCamera != null) {
            if (isPreviewing) {
                deviceCamera.stopPreview();
                isPreviewing = false;
            }
            deviceCamera.setPreviewCallback(null);
            deviceCamera.release();
            deviceCamera = null;
        }
    }
}
标签: AndroidCamera1

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。