Skip to content

Commit fbee310

Browse files
committed
Move SimpleCache creation in PlayerDataSource to avoid an IllegalStateException
This IllegalStateException, almost not reproducible, indicates that another SimpleCache instance uses the cache folder, which was so trying to be created at least twice. Moving the SimpleCache creation in PlayerDataSource should avoid this exception.
1 parent 7d6bf4b commit fbee310

2 files changed

Lines changed: 50 additions & 25 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,37 @@
11
package org.schabi.newpipe.player.helper;
22

33
import android.content.Context;
4-
import android.util.Log;
54

65
import androidx.annotation.NonNull;
76
import androidx.annotation.Nullable;
87

9-
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
108
import com.google.android.exoplayer2.upstream.DataSource;
119
import com.google.android.exoplayer2.upstream.DefaultDataSource;
1210
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
1311
import com.google.android.exoplayer2.upstream.FileDataSource;
1412
import com.google.android.exoplayer2.upstream.TransferListener;
1513
import com.google.android.exoplayer2.upstream.cache.CacheDataSink;
1614
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
17-
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
1815
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
1916

2017
import org.schabi.newpipe.player.datasource.YoutubeHttpDataSource;
2118

22-
import java.io.File;
23-
2419
/* package-private */ final class CacheFactory implements DataSource.Factory {
25-
private static final String TAG = CacheFactory.class.getSimpleName();
26-
27-
private static final String CACHE_FOLDER_NAME = "exoplayer";
2820
private static final int CACHE_FLAGS = CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR;
29-
private static SimpleCache cache;
3021

3122
private final long maxFileSize;
3223
private final Context context;
3324
private final String userAgent;
3425
private final TransferListener transferListener;
3526
private final DataSource.Factory upstreamDataSourceFactory;
27+
private final SimpleCache simpleCache;
3628

3729
public static class Builder {
3830
private final Context context;
3931
private final String userAgent;
4032
private final TransferListener transferListener;
4133
private DataSource.Factory upstreamDataSourceFactory;
34+
private SimpleCache simpleCache;
4235

4336
Builder(@NonNull final Context context,
4437
@NonNull final String userAgent,
@@ -53,34 +46,31 @@ public void setUpstreamDataSourceFactory(
5346
this.upstreamDataSourceFactory = upstreamDataSourceFactory;
5447
}
5548

49+
public void setSimpleCache(@NonNull final SimpleCache simpleCache) {
50+
this.simpleCache = simpleCache;
51+
}
52+
5653
public CacheFactory build() {
57-
return new CacheFactory(context, userAgent, transferListener,
54+
if (simpleCache == null) {
55+
throw new IllegalStateException("No SimpleCache instance has been specified. "
56+
+ "Please specify one with setSimpleCache");
57+
}
58+
return new CacheFactory(context, userAgent, transferListener, simpleCache,
5859
upstreamDataSourceFactory);
5960
}
6061
}
6162

6263
private CacheFactory(@NonNull final Context context,
6364
@NonNull final String userAgent,
6465
@NonNull final TransferListener transferListener,
66+
@NonNull final SimpleCache simpleCache,
6567
@Nullable final DataSource.Factory upstreamDataSourceFactory) {
6668
this.context = context;
6769
this.userAgent = userAgent;
6870
this.transferListener = transferListener;
71+
this.simpleCache = simpleCache;
6972
this.upstreamDataSourceFactory = upstreamDataSourceFactory;
7073

71-
final File cacheDir = new File(context.getExternalCacheDir(), CACHE_FOLDER_NAME);
72-
if (!cacheDir.exists()) {
73-
//noinspection ResultOfMethodCallIgnored
74-
cacheDir.mkdir();
75-
}
76-
77-
if (cache == null) {
78-
final LeastRecentlyUsedCacheEvictor evictor
79-
= new LeastRecentlyUsedCacheEvictor(PlayerHelper.getPreferredCacheSize());
80-
cache = new SimpleCache(cacheDir, evictor, new StandaloneDatabaseProvider(context));
81-
Log.d(TAG, "initExoPlayerCache: cacheDir = " + cacheDir.getAbsolutePath());
82-
}
83-
8474
maxFileSize = PlayerHelper.getPreferredFileSize();
8575
}
8676

@@ -112,7 +102,8 @@ public DataSource createDataSource() {
112102
.createDataSource();
113103

114104
final FileDataSource fileSource = new FileDataSource();
115-
final CacheDataSink dataSink = new CacheDataSink(cache, maxFileSize);
116-
return new CacheDataSource(cache, dataSource, fileSource, dataSink, CACHE_FLAGS, null);
105+
final CacheDataSink dataSink = new CacheDataSink(simpleCache, maxFileSize);
106+
return new CacheDataSource(simpleCache, dataSource, fileSource, dataSink, CACHE_FLAGS,
107+
null);
117108
}
118109
}

app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.schabi.newpipe.player.helper;
22

33
import android.content.Context;
4+
import android.util.Log;
45

56
import androidx.annotation.NonNull;
67
import androidx.annotation.Nullable;
78

9+
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
810
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
911
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
1012
import com.google.android.exoplayer2.source.dash.DashMediaSource;
@@ -18,12 +20,16 @@
1820
import com.google.android.exoplayer2.upstream.DefaultDataSource;
1921
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
2022
import com.google.android.exoplayer2.upstream.TransferListener;
23+
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
24+
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
2125

2226
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeOtfDashManifestCreator;
2327
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubePostLiveStreamDvrDashManifestCreator;
2428
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeProgressiveDashManifestCreator;
2529
import org.schabi.newpipe.player.datasource.YoutubeHttpDataSource;
2630

31+
import java.io.File;
32+
2733
public class PlayerDataSource {
2834

2935
public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
@@ -43,6 +49,18 @@ public class PlayerDataSource {
4349
*/
4450
private static final int MAXIMUM_SIZE_CACHED_GENERATED_MANIFESTS_PER_CACHE = 500;
4551

52+
/**
53+
* The folder name in which the ExoPlayer cache will be written.
54+
*/
55+
private static final String CACHE_FOLDER_NAME = "exoplayer";
56+
57+
/**
58+
* The {@link SimpleCache} instance which will be used to build
59+
* {@link com.google.android.exoplayer2.upstream.cache.CacheDataSource}s instances (with
60+
* {@link CacheFactory}).
61+
*/
62+
private static SimpleCache cache;
63+
4664
private final int continueLoadingCheckIntervalBytes;
4765
private final CacheFactory.Builder cacheDataSourceFactoryBuilder;
4866
private final DataSource.Factory cachelessDataSourceFactory;
@@ -51,8 +69,24 @@ public PlayerDataSource(@NonNull final Context context,
5169
@NonNull final String userAgent,
5270
@NonNull final TransferListener transferListener) {
5371
continueLoadingCheckIntervalBytes = PlayerHelper.getProgressiveLoadIntervalBytes(context);
72+
final File cacheDir = new File(context.getExternalCacheDir(), CACHE_FOLDER_NAME);
73+
if (!cacheDir.exists()) {
74+
//noinspection ResultOfMethodCallIgnored
75+
cacheDir.mkdir();
76+
}
77+
78+
if (cache == null) {
79+
final LeastRecentlyUsedCacheEvictor evictor
80+
= new LeastRecentlyUsedCacheEvictor(PlayerHelper.getPreferredCacheSize());
81+
cache = new SimpleCache(cacheDir, evictor, new StandaloneDatabaseProvider(context));
82+
Log.d(PlayerDataSource.class.getSimpleName(), "initExoPlayerCache: cacheDir = "
83+
+ cacheDir.getAbsolutePath());
84+
}
85+
5486
cacheDataSourceFactoryBuilder = new CacheFactory.Builder(context, userAgent,
5587
transferListener);
88+
cacheDataSourceFactoryBuilder.setSimpleCache(cache);
89+
5690
cachelessDataSourceFactory = new DefaultDataSource.Factory(context,
5791
new DefaultHttpDataSource.Factory().setUserAgent(userAgent))
5892
.setTransferListener(transferListener);

0 commit comments

Comments
 (0)