Android ExoPlayer ExoPlaybackException

android.exoplayer2.ExoPlaybackException 是 ExoPlayer 播放过程中抛出的通用异常,通常由底层媒体源、解码器或网络问题引发。以下是系统性排查指南:

一、异常类型与核心原因

异常子类 触发场景
ExoPlaybackException.SourceError 媒体源加载失败(网络错误/文件损坏/格式不支持)、元数据解析异常、DRM认证失败
ExoPlaybackException.RendererError 解码器初始化失败、硬件编码格式不支持、渲染器配置错误(视频尺寸/像素格式不匹配)
ExoPlaybackException.LoadError 媒体数据加载超时、缓存不足、网络中断(HTTPS/SSL握手失败)

1.关键方法

通过 getSourceException() 获取底层异常对象,进一步定位问题根源。例如:

try {
    player.prepare(mediaItem);
} catch (ExoPlaybackException e) {
    Throwable cause = e.getSourceException();
    if (cause instanceof HttpDataSourceException) {
        Log.e("ExoPlayer", "HTTP 错误: " + ((HttpDataSourceException) cause).responseCode);
    }
}

二、关键排查方向

1. 网络与 SSL 问题(重点)

现象:Android 4.4 设备 HTTPS 请求失败,Android 5.0+ 正常
原因:Android 4.4 默认禁用 TLSv1.1/TLSv1.2
解决方案

  • application中增加代码
// 在 Application.onCreate() 中添加
try {
    ProviderInstaller.installIfNeeded(getApplicationContext());
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(null, null, null);
    sslContext.createSSLEngine();
} catch (Exception e) {
    e.printStackTrace();
}
  • 代码配置:通过 OkHttpClient 或自定义 DataSource.Factory 启用 TLSv1.2。
// 1. 创建自定义 SSLSocketFactory
public class Tls12SocketFactory extends SSLSocketFactory {
    private static final String[] TLS_V12_ONLY = {"TLSv1.2"};
    private final SSLSocketFactory delegate;
 
    public Tls12SocketFactory(SSLSocketFactory base) {
        this.delegate = base;
    }
 
    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patchSocket(delegate.createSocket(s, host, port, autoClose));
    }
 
    private Socket patchSocket(Socket socket) {
        if (socket instanceof SSLSocket) {
            ((SSLSocket) socket).setEnabledProtocols(TLS_V12_ONLY);
        }
        return socket;
    }
 
}
 
// 2. 配置 OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(new Tls12SocketFactory(SSLContext.getDefault().getSocketFactory()))
    .connectionSpecs(Arrays.asList(
        new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2)
            .build(),
        ConnectionSpec.COMPATIBLE_TLS,
        ConnectionSpec.CLEARTEXT
    ))
    .build();

// 配置 ExoPlayer DataSource
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory()
    .setHttpClient(okHttpClient) // 核心:注入自定义 OkHttpClient
    .setUserAgent("CustomUserAgent")
    .setConnectTimeoutMs(30000);
 
ExoPlayer player = new ExoPlayer.Builder(context)
    .setDataSourceFactory(dataSourceFactory)
    .build();

验证:通过 adb logcat | grep 'ExoPlayer' 检查 SSL 日志

2. 媒体源与数据问题

检查点

  • 媒体 URL 有效性(使用浏览器/curl 测试)
  • 媒体格式支持性(HLS/DASH/MP4 等)
  • 媒体文件完整性(本地播放测试)

调试工具

// 解析媒体元数据
MediaInfo mediaInfo = new MediaInfo(mediaUrl);

// 配置自定义参数
DefaultHttpDataSource dataSource = new DefaultHttpDataSource.Factory()
    .setUserAgent("CustomUserAgent")
    .setConnectTimeoutMs(30000)
    .createDataSource();

3. 解码器与渲染问题

常见错误

  • MediaCodecRenderer 报错:设备不支持 H.265 等编码格式
  • 视频尺寸/像素格式不匹配

解决方案

// 启用软件解码器
RenderersFactory renderersFactory = new DefaultRenderersFactory(context)
    .setEnableDecoderFallback(true);

// 监听视频尺寸变更
player.addListener(new Player.EventListener() {
    @Override
    public void onVideoSizeChanged(VideoSize videoSize) {
        // 调整 Surface 尺寸
    }
});

4. DRM 保护内容

现象:DRM session error 或 License acquisition failed
排查

  • 确认 DRM 许可证 URL 和认证信息正确性
  • 检查网络请求是否携带正确 DRM 请求头(如 Authorization)

三、调试与日志分析

// 捕获异常堆栈
player.addListener(new Player.EventListener() {
    @Override
    public void onPlayerError(ExoPlaybackException error) {
        Log.e("ExoPlayer", "Error stack trace: " + Log.getStackTraceString(error));
    }
});

日志过滤

adb logcat | grep 'ExoPlayer' -i

四、版本兼容性建议

  • ExoPlayer 版本:使用最新稳定版(如 2.X/3.X)
  • Android 版本适配
    • Android 4.4:强制启用 TLSv1.2,避免 HTTP/2
    • Android 5.0+:检查 android:usesCleartextTraffic 配置

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐