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

Flutter FlickVideoPlayer安卓端无法播放SSL服务器视频求助

问题描述

后端服务器受SSL保护,REST API运行正常,iOS端视频播放器可正常播放视频,但安卓端使用ExoPlayer无法播放,控制台返回如下错误:

E/ExoPlayerImplInternal(12438):   Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(12438):   Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(12438):   Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(12438):   Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

当前网络安全配置文件如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">my-addr.eu</domain>
        <trust-anchors>
            <certificates src="@raw/my_ca"/>
        </trust-anchors>
    </domain-config>
</network-security-config>

证书路径为raw/my_ca.pem,移动或删除该文件会触发其他错误,说明IDE能识别该文件。需解决以下问题:

  • 如何修复安卓端无法播放的问题?
  • 为何安卓端出问题而iOS端正常?

问题分析与修复方案

核心原因

安卓与iOS对自定义CA证书的处理逻辑存在差异:

  • iOS系统网络栈会自动应用用户或应用内配置的信任锚,第三方视频播放器默认复用系统网络配置,只要证书有效就能建立SSL连接。
  • 安卓的network-security-config仅对系统默认的HTTP客户端生效,但ExoPlayer使用独立的HTTP数据源实现,不会自动读取该配置,因此需要单独配置SSL信任逻辑。

此外,若my_ca.pem仅包含中间CA而非完整根CA,也会导致证书链验证失败。

修复步骤

1. 为ExoPlayer配置自定义SSL信任管理器

通过OkHttp为ExoPlayer构建带自定义信任锚的数据源,代码示例如下:

// 加载raw目录下的CA证书
InputStream certInputStream = getResources().openRawResource(R.raw.my_ca);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(certInputStream);

// 初始化密钥库并添加证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry("ca", cert);

// 创建信任管理器
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

// 构建自定义SSL上下文
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());

// 配置OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
        .build();

// 为ExoPlayer设置自定义数据源工厂
OkHttpDataSource.Factory dataSourceFactory = new OkHttpDataSource.Factory(okHttpClient);
ExoPlayer player = new ExoPlayer.Builder(this)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory))
        .build();

2. 验证证书链完整性

确保my_ca.pem包含完整的根CA证书。若服务器证书由中间CA签发,需将根CA与中间CA合并为一个PEM文件(按顺序拼接),放入raw目录,否则安卓无法完成证书链的信任验证。

3. 确认网络安全配置兼容性

若应用目标SDK为Android 7.0(API 24)及以上,当前network-security-config配置对系统HTTP客户端有效,但不影响ExoPlayer,无需额外修改;若为更低版本,可添加debug-overrides临时调试,但这不是解决当前问题的核心。

安卓与iOS差异说明

  • iOS端:系统统一管理信任锚,所有网络请求(包括第三方播放器)默认复用系统信任配置,只要证书本身合法且被信任,就能正常完成SSL握手。
  • 安卓端:ExoPlayer的默认HTTP数据源(DefaultHttpDataSource)独立于系统网络配置,不会自动读取network-security-config中的信任规则,必须手动配置信任管理器才能认可自定义CA证书,否则会触发证书路径验证失败的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:10:31