4. 日志采集与初步过滤:adb logcat 抓取 ExoPlayer 相关日志、过滤 SecurityException/Denied 关键字、定位关键时间戳
4.1 现象识别
当 ExoPlayer 因权限不足无法播放时,典型现象包括:
- 播放器回调
onPlayerError,错误类型为PlaybackException.ERROR_CODE_IO_UNSPECIFIED - 播放界面显示“无法播放此视频”或空白黑屏
- 日志中频繁出现 SecurityException 或 Access Denied 关键字
这些现象提示我们需要立即启动日志采集,定位具体哪个资源(文件、URI、证书)被拒绝访问。
4.2 数据采集:使用 adb logcat 抓取 ExoPlayer 日志
打开终端,执行以下命令将日志持续写入文件,以便事后分析:
adb logcat -v time -f /sdcard/exo_log.txt *:V
关键参数说明:
| 参数 | 作用 |
|---|---|
-v time | 为每条日志附加时间戳(精确到毫秒) |
-f /sdcard/exo_log.txt | 将输出重定向到设备文件,避免终端缓冲丢失 |
*:V | 显示所有级别的日志(Verbose 及以上),不漏掉任何线索 |
贴士: 如设备无 root 权限,可将日志输出到应用私有目录
/data/data/<package>/files/ 或使用 adb logcat -d > local.log 截取当前缓冲区内容。
同时,建议在 ExoPlayer 初始化前后增加自定义日志标记,方便过滤:
adb logcat -v time -s ExoPlayerImpl:V MediaSource:V *:E
此命令只保留 ExoPlayerImpl 和 MediaSource 的详细信息,同时显示所有错误日志。
4.3 初步过滤:使用 grep 提取 SecurityException / Denied 关键字
将抓取到的日志文件 pull 到本地,然后用 grep 快速定位可疑行:
adb pull /sdcard/exo_log.txt ./
grep -in "SecurityException\|Denied\|Permission" exo_log.txt > filtered_log.txt
more filtered_log.txt
常见匹配模式示例:
| 模式 | 典型日志片段 | 含义 |
|---|---|---|
SecurityException |
java.lang.SecurityException: Neither user 10123 nor current process has android.permission.INTERNET |
缺少网络权限 |
Denied |
open failed: EACCES (Permission denied) for /storage/emulated/0/video.mp4 |
文件系统访问被拒绝 |
Permission |
No permission to access URI: content://media/external/video/media/123 |
Content URI 权限缺失 |
注意: 不要只过滤异常堆栈第一行,还要向后看
Caused by 链,底层 `PermissionDenied` 可能被包装在多级异常中。
4.4 定位关键时间戳
在过滤后的日志中,找到第一次出现 SecurityException/Denied 的时间点,并以此为中心前后各扩展 2 秒,观察关联事件:
- 时间戳格式(如
01-23 14:30:15.123)对应文件中的第一列。 - 记录该时间戳,用于与播放器初始化、资源加载、DRM 请求等操作对齐。
- 检查该时间戳附近是否有 ExoPlayer 的
onLoadError、onPlayerError回调日志。
以下命令可输出时间戳前后的上下文:
# 假设时间戳为 "01-23 14:30:15.123"
grep -n "01-23 14:30:1[3-7]" exo_log.txt | head -50
4.5 修复动作:根据日志确认权限缺口
对照过滤结果,按优先级执行修复:
- 网络权限:在 AndroidManifest.xml 中追加
<uses-permission android:name="android.permission.INTERNET" />。 - 文件/存储权限:Android 11+ 需使用
MediaStore或SAF;传统文件路径需动态请求READ_EXTERNAL_STORAGE。 - Content URI 权限:为
Intent添加FLAG_GRANT_READ_URI_PERMISSION,或在ContentResolver中takePersistableUriPermission。 - DRM 证书权限:确认设备是否支持 Widevine,以及证书路径是否可读。
4.6 复测:重新采集并验证修复
修改代码后,重新安装应用,再次执行相同的 adb logcat 命令,并过滤相同关键字:
adb logcat -v time -f /sdcard/exo_verify.txt *:V
# 在设备上复现播放操作
adb pull /sdcard/exo_verify.txt ./
grep -c "SecurityException\|Denied" exo_verify.txt
若返回 0,则权限问题已解决;否则返回 1+,需返回步骤 4.2 检查遗漏的日志行。
4.7 预防:日志采集最佳实践
- 在 ExoPlayer 初始化时,主动输出当前应用的权限列表:
context.checkSelfPermission()结果打印到 Logcat。 - 使用
exoplayer2:exoplayer-core-2.19.1及以上版本,其内部日志更详细地输出权限失败原因。 - 建立自动化测试脚本,在每一次 CI 构建后自动抓取 Logcat 并扫描 SecurityException 关键字。
- 在安卓 13+ 上注意通知权限(
POST_NOTIFICATIONS)也可能导致播放中断,需一并检查。