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

Android 8三星设备使用SCameraCaptureSession调用setRepeatingRequest报错

解决Android 8三星设备SCameraCaptureSession.setRepeatingRequest的Surface配置异常问题

我之前也碰到过类似的坑,在Android 8的三星设备上用Camera2 API录制视频时正好遇到这个崩溃,给你分享下解决思路和具体步骤:

问题根源

Android 8(API 26)开始,Camera2 API对Surface的有效性校验变得更严格,尤其是三星设备会额外检查Surface是否完成了完整的初始化流程。低版本系统可能允许你提前把MediaRecorder的Surface绑定到CaptureRequest,但Android 8的三星设备会直接抛出IllegalArgumentException,因为此时MediaRecorder的Surface还没完成配置(比如还没调用prepare())。

具体解决方案

  • 确保MediaRecorder的Surface完全初始化后再传入CaptureSession
    一定要先完成MediaRecorder的所有配置(输出格式、编码、文件路径、视频分辨率等),调用mediaRecorder.prepare()之后,再获取它的Surface。绝对不能提前获取Surface再去配置MediaRecorder,顺序错了就会触发这个异常。
    示例流程:

    // 1. 先配置MediaRecorder的各项参数
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mediaRecorder.setOutputFile(outputFilePath);
    mediaRecorder.setVideoEncodingBitRate(10000000);
    mediaRecorder.setVideoFrameRate(30);
    // 这里要注意选择Camera支持的尺寸,后面会讲
    mediaRecorder.setVideoSize(recorderWidth, recorderHeight);
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    
    // 2. 调用prepare()完成初始化
    mediaRecorder.prepare();
    
    // 3. 此时再获取有效的Surface
    Surface recorderSurface = mediaRecorder.getSurface();
    
  • 在CaptureSession配置完成后再创建CaptureRequest
    必须等到SCameraCaptureSession的onConfigured()回调触发后,再创建包含MediaRecorder Surface的CaptureRequest并调用setRepeatingRequest。这一步是确保CaptureSession已经正确识别并配置了传入的Surface。
    示例代码:

    // 假设已经有previewSurface用于预览
    List<Surface> surfaces = Arrays.asList(previewSurface, recorderSurface);
    cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            // 这里才是安全创建录制请求的时机
            try {
                CaptureRequest.Builder recordRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
                recordRequestBuilder.addTarget(previewSurface);
                recordRequestBuilder.addTarget(recorderSurface);
                // 提交重复请求开始录制
                session.setRepeatingRequest(recordRequestBuilder.build(), null, backgroundHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            // 处理配置失败的逻辑,比如提示用户重试
        }
    }, backgroundHandler);
    
  • 匹配Camera支持的视频尺寸
    三星Android 8设备对Surface尺寸的匹配要求很严格,必须确保MediaRecorder设置的视频尺寸是当前Camera支持的输出尺寸。可以通过CameraCharacteristics获取支持的尺寸列表,选择最合适的那一个:

    // 获取Camera的特性
    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
    StreamConfigurationMap configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    // 获取MediaRecorder支持的输出尺寸
    Size[] supportedSizes = configMap.getOutputSizes(MediaRecorder.class);
    // 选择和你期望的分辨率最匹配的尺寸(这里可以自己实现chooseOptimalSize方法)
    Size optimalSize = chooseOptimalSize(supportedSizes, desiredWidth, desiredHeight);
    // 设置给MediaRecorder
    mediaRecorder.setVideoSize(optimalSize.getWidth(), optimalSize.getHeight());
    
  • 提前校验Surface有效性
    在提交CaptureRequest前,可以先检查Surface是否有效,避免传入无效的Surface导致崩溃:

    if (recorderSurface != null && recorderSurface.isValid()) {
        // 安全创建并提交请求
    } else {
        // 重新初始化MediaRecorder和Surface
    }
    

总结

这个问题本质是Android 8开始的API行为变更加上三星设备的严格校验导致的,只要按照正确的顺序初始化MediaRecorder和Surface,确保尺寸匹配,并且在CaptureSession配置完成后再提交请求,就能解决这个崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:33:14