You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android无布局编程获取Camera2预览帧的问题求助

解决动态创建TextureView获取Camera2预览帧空白的问题

我来帮你拆解下这个问题的核心:你遇到的空白帧问题,本质是动态创建的TextureView没有走完正确的初始化流程,导致Camera2的预览数据无法正常渲染到Surface上,加上你在工作线程操作UI组件,进一步加剧了状态异常。下面是具体的解决方向和修正方案:

1. 必须在UI线程操作TextureView

TextureView是Android的UI组件,所有和它相关的创建、配置、回调监听操作都必须在**主线程(UI线程)**执行。你提到代码运行在工作线程,这直接违反了Android的View操作规则,会导致SurfaceTexture无法正常初始化。

修正方式:用runOnUiThread或者Handler将TextureView的创建逻辑切换到主线程:

// 在你的工作线程中,切换到UI线程处理TextureView初始化
mainActivity.runOnUiThread(() -> {
    // 这里才是创建TextureView的正确时机
    textureView = new TextureView(mainActivity);
    // 接下来设置SurfaceTexture监听、配置尺寸等
});

2. 不要手动给TextureView设置SurfaceTexture

你之前写的textureView.setSurfaceTexture(new SurfaceTexture(100));是错误操作——TextureView内部会自动管理SurfaceTexture的生命周期,手动设置会破坏它的初始化流程,导致Camera的预览数据无法正确绑定到Surface上。

直接删掉这行代码,让TextureView自己生成SurfaceTexture。

3. 等待SurfaceTexture就绪后再关联Camera2

动态创建的TextureView不会像布局里的View那样自动触发初始化,必须通过SurfaceTextureListener监听它的就绪状态,在onSurfaceTextureAvailable回调中再去创建Surface并绑定Camera2的会话。

完整的修正代码示例:

mainActivity.runOnUiThread(() -> {
    textureView = new TextureView(mainActivity);
    // 设置TextureView的尺寸(建议和Camera预览尺寸一致)
    textureView.setLayoutParams(new ViewGroup.LayoutParams(1920, 1080));
    
    textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
            // 此时SurfaceTexture才真正就绪,创建Surface并关联Camera2
            surface = new Surface(surfaceTexture);
            // 这里调用你初始化CameraDevice、创建CaptureSession的逻辑
            initCamera2Session(surface);
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
            // 可选:处理预览尺寸变化的逻辑
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            // 释放资源
            if (surface != null) surface.release();
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
            // 这个回调表示有新的预览帧更新,在这里获取Bitmap才是有效的
            Bitmap frame = textureView.getBitmap();
            // 执行你的保存帧操作
            saveFrameToFile(frame);
        }
    });
});

关键补充说明

  • 为什么布局中的TextureView正常?因为布局里的View会被系统自动添加到视图层级,在附着到窗口时触发SurfaceTexture的初始化流程,自动调用onSurfaceTextureAvailable。
  • 获取Bitmap的时机:务必在onSurfaceTextureUpdated回调中获取,这个回调确保SurfaceTexture已经更新了最新的预览帧,此时getBitmap()拿到的才是有效数据。
  • 不需要添加到视图层级:动态创建的TextureView不需要添加到Activity的布局中,只要它的SurfaceTexture就绪,就能接收Camera的预览数据。

内容的提问来源于stack exchange,提问作者Stream

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:12:44