Android MediaPlayer IO异常(E(-1003,-403))与wmsAuth密钥刷新适配问题
解决MediaPlayer在部分设备上无法识别403错误导致密钥刷新失效的问题
这个问题我之前也踩过坑——不同Android设备/版本对HTTP 403 Forbidden错误的异常封装差异确实头疼,有的设备会通过MediaPlayer.OnErrorListener返回明确的MEDIA_ERROR_SERVER_DIED(-1003)和extra=-403,但有的只会抛出泛化的IOException,完全没有明确错误码。下面是我实践过的可靠解决方案:
1. 保留原有明确错误码的处理逻辑
先把你原来的逻辑保留,覆盖那些能返回明确错误码的设备:
mediaPlayer.setOnErrorListener((mp, what, extra) -> { // 匹配明确的403错误信号 if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED && extra == -403) { refreshWmsAuthKeyAndRetry(); return true; // 表示已处理该错误 } return false; // 其他错误交给默认处理 });
2. 给IOException添加403识别逻辑
针对那些只抛IOException的设备,我们需要深入异常链,从底层提取403的信号:
核心思路
遍历异常的cause链,从两个维度判断是否是403错误:
- 检查异常类型是否为
HttpRetryException(部分设备会把HTTP错误封装成这个类型),直接获取响应码 - 作为 fallback,检查异常消息中是否包含"403"或"Forbidden"关键字(虽然依赖字符串,但在极端场景下有用)
实现代码
try { mediaPlayer.setDataSource(yourWmsAuthUrl); mediaPlayer.prepare(); mediaPlayer.start(); } catch (IOException e) { if (isForbiddenError(e)) { // 确认是403错误,触发密钥刷新 refreshWmsAuthKeyAndRetry(); } else { // 处理其他IO异常(比如网络断开、文件损坏等) handleOtherPlaybackError(e); } } // 辅助方法:判断异常是否由403 Forbidden导致 private boolean isForbiddenError(IOException e) { Throwable currentCause = e; while (currentCause != null) { // 情况1:异常是HttpRetryException,直接取响应码 if (currentCause instanceof HttpRetryException) { HttpRetryException retryEx = (HttpRetryException) currentCause; if (retryEx.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) { return true; } } // 情况2:异常消息包含403或Forbidden关键字 String errorMsg = currentCause.getMessage(); if (errorMsg != null && (errorMsg.contains("403") || errorMsg.contains("Forbidden"))) { return true; } currentCause = currentCause.getCause(); } return false; }
3. 进阶优化(可选)
如果你的项目有条件切换到ExoPlayer,我非常推荐——它的错误处理体系更统一,会把HTTP错误封装成HttpDataSourceException,直接提供getResponseCode()方法,不用再费劲遍历异常链,代码会简洁很多。
总结
这种问题本质是Android生态的碎片化导致的错误封装不一致,通过「明确错误码处理 + 异常链深度分析」的组合方案,基本能覆盖90%以上的设备场景,确保你的wmsAuth密钥刷新逻辑正常触发。
内容的提问来源于stack exchange,提问作者A_rmas
相关产品推荐
相关产品推荐

