使用ExoPlayer DownloadService下载HLS视频时401崩溃问题排查
ExoPlayer下载HLS时偶尔因401崩溃的排查与解决
可能的原因
- 令牌时效性与请求时序差异:预授权令牌在下载过程中过期(如下载大文件时,分片请求晚于m3u8请求,令牌刚好在分片请求时失效)。你用过期链接测试时是初始请求就触发401,ExoPlayer下载管理器能正常标记失败;但下载过程中令牌过期导致的401,因未被正确捕获而触发崩溃。
- HttpDataSource错误处理配置缺失:默认的
DefaultHttpDataSource会对非200-299的响应码抛出InvalidResponseCodeException,如果这个异常未被ExoPlayer下载逻辑捕获(比如并发线程池未处理),就会导致应用崩溃。 - 并发请求的令牌冲突:使用固定线程池并发下载时,多个分片请求同时使用同一令牌,可能触发服务器的令牌校验限制(如同一令牌并发请求次数上限),导致部分请求返回401。
- 缓存与令牌不匹配:自定义的
OPDownloadCacheKeyFactory若未将令牌纳入缓存key生成逻辑,可能缓存了带旧令牌的m3u8文件,后续分片请求使用过期令牌。
解决与排查步骤
1. 先解决崩溃问题:配置HttpDataSource捕获401异常
修改你的getHttpDataSourceFactory方法,允许无效响应码或自定义异常处理,避免未捕获的异常导致崩溃:
private fun getHttpDataSourceFactory(context: Context): HttpDataSource.Factory { return DefaultHttpDataSource.Factory() .setUserAgent("Your-App-User-Agent") // 允许非200响应码,避免抛出异常导致崩溃,ExoPlayer会自动标记下载失败 .setAllowInvalidResponseCodes(true) // 若需要动态更新令牌,可添加请求头拦截逻辑 .setDefaultRequestProperties( mapOf("Authorization" to "Bearer ${yourTokenProvider.getValidToken()}") ) }
或者自定义HttpDataSource,在请求前刷新令牌,确保每次请求用最新令牌:
class TokenRefreshingHttpDataSourceFactory( private val tokenProvider: () -> String ) : HttpDataSource.Factory { override fun createDataSource(): HttpDataSource { return object : DefaultHttpDataSource("Your-App-User-Agent") { override fun open(dataSpec: DataSpec): Long { // 每次请求前更新授权头,确保令牌有效 val updatedDataSpec = dataSpec.buildUpon() .setRequestProperty("Authorization", "Bearer ${tokenProvider.invoke()}") .build() return try { super.open(updatedDataSpec) } catch (e: HttpDataSource.InvalidResponseCodeException) { if (e.responseCode == 401) { // 可选:在这里触发令牌刷新,重试请求 // val newToken = refreshToken() // val retrySpec = updatedDataSpec.buildUpon() // .setRequestProperty("Authorization", "Bearer $newToken") // .build() // super.open(retrySpec) throw e // 抛出异常让ExoPlayer标记下载失败,而非崩溃 } else { throw e } } } } } }
2. 排查401的根源
- 开启ExoPlayer日志:添加日志配置,查看崩溃时的请求URL、响应头和令牌信息,确认是m3u8请求还是分片请求触发401。
- 模拟令牌过期场景:启动下载后,手动让令牌失效(如调用后端接口吊销令牌),观察是否能复现崩溃。
- 检查服务器日志:查看返回401的请求详情,确认是令牌过期、无效还是并发限制导致。
- 校验缓存key逻辑:确保
OPDownloadCacheKeyFactory生成的缓存key包含令牌的唯一标识,避免缓存旧的授权内容。
3. 优化下载逻辑
- 限制并发下载数:若服务器对同一令牌的并发请求有限制,可降低
MAX_PARALLEL_DOWNLOADS的值。 - 添加下载监听的错误处理:在
OPDownloadListener中监听onDownloadFailed事件,针对401错误做重试或用户提示。
内容的提问来源于stack exchange,提问作者Akshansh Choudhary
相关产品推荐
相关产品推荐

