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

升级targetSDK至31后三星A系列Android12设备SurfaceView黑屏

解决targetSDK 31升级后三星A系列Android 12设备SurfaceView黑屏问题

这个问题我之前在适配Android 12的时候也碰到过类似的情况,尤其是三星的定制系统对SurfaceView的行为有一些特殊调整,结合targetSDK升级到31后的API变更,我给你几个可行的排查和解决方案:

1. 确保解码器在Surface完全就绪后再配置

Android 12(API 31)对Surface的可用性校验变得更严格,如果你在Surface还未完全创建完成时就调用decoder.configure(),很可能导致解码器无法正确绑定Surface,从而出现黑屏。建议把解码器的配置逻辑移到SurfaceHolder.Callback的surfaceCreated回调中:

mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // 这里Surface已经完全就绪,再初始化解码器
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
        try {
            decoder.configure(mediaFormat, holder.getSurface(), null, 0);
            decoder.start();
        } catch (IllegalStateException | IOException e) {
            // 即使无法获取用户日志,建议在本地添加异常捕获逻辑,方便后续排查
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 可选:如果Surface尺寸变化,调整解码器输出参数
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // 及时释放解码器资源,避免内存泄漏
        if (decoder != null) {
            decoder.stop();
            decoder.release();
            decoder = null;
        }
    }
});

2. 替换SurfaceView为TextureView

三星的Android 12定制系统对SurfaceView的兼容性不如TextureView,TextureView作为View的子类,渲染逻辑更灵活,不受SurfaceFlinger的部分限制,很多时候能直接解决黑屏问题。替换后的代码示例如下:

TextureView mTextureView = findViewById(R.id.video_texture_view);
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Surface decoderSurface = new Surface(surface);
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
        try {
            decoder.configure(mediaFormat, decoderSurface, null, 0);
            decoder.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // 适配Surface尺寸变化
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        if (decoder != null) {
            decoder.stop();
            decoder.release();
            decoder = null;
        }
        surface.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // 可选:监听帧更新事件
    }
});

3. 补充MediaFormat的必要参数

API 31对解码器的配置参数要求更严格,仅指定宽高和格式可能不足以让解码器正常输出帧。建议补充帧率、码率,以及H264必需的SPS/PPS数据(如果有的话):

MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
// 设置帧率,根据你的视频实际帧率调整
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
// 设置合理的码率,示例值可根据实际情况调整
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1280 * 720 * 30 * 2);

// 如果你的H264流包含SPS和PPS数据,一定要添加到MediaFormat中
byte[] spsData = ...; // 从视频流中解析出的SPS字节数组
byte[] ppsData = ...; // 从视频流中解析出的PPS字节数组
mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(spsData));
mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(ppsData));

decoder.configure(mediaFormat, surface, null, 0);

4. 确认硬件加速和权限配置

SurfaceView依赖硬件加速,Android 12可能默认的配置有变化,建议在Manifest中明确开启硬件加速:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:hardwareAccelerated="true" <!-- 确保开启硬件加速 -->
    android:theme="@style/AppTheme">
    ...
</application>

如果视频数据来自外部存储,还要确保已申请Android 12对应的存储权限(READ_MEDIA_VIDEO),避免因权限问题导致解码失败。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:15:58