CarGuo/GSYVideoPlayer · error · IllegalStateException
ExoPlayer Cache 未初始化,请先播放视频
Error message
ExoPlayer Cache 未初始化,请先播放视频
What it means
Media3CacheExportUtils needs an already-initialized ExoPlayer SimpleCache to read cached segments from; it calls ExoSourceManager.acquireCacheSingleInstance(context, null) which returns null when caching was never enabled or the folder is locked with fallback (fallbackWhenLocked path returned null). Throwing IllegalStateException tells the caller the export precondition (a played, cached video) is not met.
Source
Thrown at gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/Media3CacheExportUtils.java:85
String fileName = "video_export_" + System.currentTimeMillis() + ".mp4";
finalTargetFile = new File(dir, fileName);
}
// 关键修复:确保父文件夹存在,否则会报 FileNotFoundException
File parentDir = finalTargetFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
boolean created = parentDir.mkdirs();
if (!created && !parentDir.exists()) {
throw new IOException("无法创建目录: " + parentDir.getAbsolutePath());
}
}
// --- 2. Cache 获取逻辑 (复用单例) ---
// 使用 GSYVideoPlayer 现有的单例 Cache
// 修复了 "Another SimpleCache instance uses the folder" 错误
Cache cache = ExoSourceManager.acquireCacheSingleInstance(context, null);
if (cache == null) {
throw new IllegalStateException("ExoPlayer Cache 未初始化,请先播放视频");
}
try {
// --- 3. 导出核心逻辑 ---
DataSpec dataSpec = new DataSpec.Builder()
.setUri(Uri.parse(videoUrl))
.setFlags(DataSpec.FLAG_ALLOW_CACHE_FRAGMENTATION)
.build();
// 使用 DefaultDataSource,如果缓存缺了一点点,它会自动联网补齐,而不是崩溃
CacheDataSource dataSource = new CacheDataSource(
cache,
new DefaultDataSource(context, true), // <--- 修正:传入 Context,支持 HTTP/HTTPS 和 File
CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR
);
try {
long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(videoUrl));
if (contentLength <= 0) {
contentLength = dataSource.open(dataSpec);View on GitHub (pinned to e5d74d3aa9)
Solutions
- Start playback (which initializes the ExoPlayer cache) before invoking export, and only enable the export UI after onPrepared
- Pre-create the cache at app start via ExoSourceManager.acquireCacheSingleInstance(context, cacheDir, true) so export always finds it
- Handle null cache gracefully: show 'video not cached yet' message instead of crashing
- Ensure export runs in the same process that owns the player cache
Example fix
// before
Cache cache = ExoSourceManager.acquireCacheSingleInstance(context, null);
if (cache == null) throw new IllegalStateException("ExoPlayer Cache 未初始化,请先播放视频");
// after - ensure cache exists up front, guard UI on result
Cache cache = ExoSourceManager.acquireCacheSingleInstance(context, null);
if (cache == null) {
callback.onExportUnavailable("Play the video first so it can be cached");
return;
} Defensive patterns
Strategy: validation
Validate before calling
Cache cache = ExoSourceManager.acquireCacheSingleInstance(context, null);
if (cache == null) {
// don't call export; initialize cache by starting playback or pre-create it
cache = ExoSourceManager.acquireCacheSingleInstance(context, new File(context.getCacheDir(), "exo"), true);
} Try / catch
try {
exportCachedVideo(context, url, target);
} catch (IllegalStateException e) {
if ("ExoPlayer Cache 未初始化,请先播放视频".equals(e.getMessage())) {
showHint("Play the video first, then export");
} else throw e;
} Prevention
- Enable the export UI only after playback has initialized the cache
- Pre-create the cache at app start in the same process
- Keep player and export in one process
When it happens
Trigger: Calling exportCachedVideo before any GSYVideoPlayer playback created the cache, when ExoSourceManager had zero cache holders (sCacheHolderMap empty), or when the cache folder was locked and the fallback overload returned null instead of a Cache.
Common situations: Export feature invoked from a screen where video never played; app was restarted and cache instance is gone but UI still offers 'export'; cache disabled in GSYVideoType/PlayerFactory config; multi-process: export runs in a process where the cache was never created.
Related errors
- Exo cache folder is locked: ${cachePath}
- Error recreate zero-size file %s
- Max count must be positive number!
- Max size must be positive number!
- 无法创建目录: ${parentDir.getAbsolutePath()}
AI-assisted analysis of CarGuo/GSYVideoPlayer@e5d74d3aa9 (2026-08-14).
Data as JSON: /api/errors/0b3ebc870ec6c0f0.
Report an issue: GitHub.