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
相关产品推荐
相关产品推荐

