206 lines
7.9 KiB
Java
206 lines
7.9 KiB
Java
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.example.exoplayertv;
|
|
|
|
import android.content.Context;
|
|
|
|
import androidx.media3.common.util.UnstableApi;
|
|
import androidx.media3.exoplayer.DefaultRenderersFactory;
|
|
import androidx.media3.exoplayer.RenderersFactory;
|
|
import androidx.media3.database.DatabaseProvider;
|
|
import androidx.media3.database.StandaloneDatabaseProvider;
|
|
import androidx.media3.datasource.cronet.CronetDataSource;
|
|
import androidx.media3.datasource.cronet.CronetUtil;
|
|
import androidx.media3.exoplayer.offline.DownloadManager;
|
|
import androidx.media3.exoplayer.offline.DownloadNotificationHelper;
|
|
import androidx.media3.datasource.DataSource;
|
|
import androidx.media3.datasource.DefaultDataSource;
|
|
import androidx.media3.datasource.DefaultHttpDataSource;
|
|
import androidx.media3.datasource.cache.Cache;
|
|
import androidx.media3.datasource.cache.CacheDataSource;
|
|
import androidx.media3.datasource.cache.NoOpCacheEvictor;
|
|
import androidx.media3.datasource.cache.SimpleCache;
|
|
import java.io.File;
|
|
import java.net.CookieHandler;
|
|
import java.net.CookieManager;
|
|
import java.net.CookiePolicy;
|
|
import java.util.concurrent.Executors;
|
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
import org.chromium.net.CronetEngine;
|
|
|
|
/** Utility methods for the demo app. */
|
|
public final class DemoUtil {
|
|
|
|
public static final String DOWNLOAD_NOTIFICATION_CHANNEL_ID = "download_channel";
|
|
|
|
/**
|
|
* Whether the demo application uses Cronet for networking. Note that Cronet does not provide
|
|
* automatic support for cookies (https://github.com/google/ExoPlayer/issues/5975).
|
|
*
|
|
* <p>If set to false, the platform's default network stack is used with a {@link CookieManager}
|
|
* configured in {@link #getHttpDataSourceFactory}.
|
|
*/
|
|
private static final boolean USE_CRONET_FOR_NETWORKING = true;
|
|
|
|
private static final String TAG = "DemoUtil";
|
|
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
|
|
|
|
private static DataSource.@MonotonicNonNull Factory dataSourceFactory;
|
|
private static DataSource.@MonotonicNonNull Factory httpDataSourceFactory;
|
|
@UnstableApi
|
|
private static @MonotonicNonNull DatabaseProvider databaseProvider;
|
|
private static @MonotonicNonNull File downloadDirectory;
|
|
@UnstableApi
|
|
private static @MonotonicNonNull Cache downloadCache;
|
|
@UnstableApi
|
|
private static @MonotonicNonNull DownloadManager downloadManager;
|
|
private static @MonotonicNonNull DownloadTracker downloadTracker;
|
|
@UnstableApi
|
|
private static @MonotonicNonNull DownloadNotificationHelper downloadNotificationHelper;
|
|
|
|
/** Returns whether extension renderers should be used. */
|
|
public static boolean useExtensionRenderers() {
|
|
return false; // Elmar: BuildConfig.USE_DECODER_EXTENSIONS;
|
|
}
|
|
|
|
@UnstableApi
|
|
public static RenderersFactory buildRenderersFactory(
|
|
Context context, boolean preferExtensionRenderer) {
|
|
@DefaultRenderersFactory.ExtensionRendererMode
|
|
int extensionRendererMode =
|
|
useExtensionRenderers()
|
|
? (preferExtensionRenderer
|
|
? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER
|
|
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
|
|
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF;
|
|
return new DefaultRenderersFactory(context.getApplicationContext())
|
|
.setExtensionRendererMode(extensionRendererMode);
|
|
}
|
|
|
|
public static synchronized DataSource.Factory getHttpDataSourceFactory(Context context) {
|
|
if (httpDataSourceFactory == null) {
|
|
if (USE_CRONET_FOR_NETWORKING) {
|
|
context = context.getApplicationContext();
|
|
@Nullable CronetEngine cronetEngine = CronetUtil.buildCronetEngine(context);
|
|
if (cronetEngine != null) {
|
|
httpDataSourceFactory =
|
|
new CronetDataSource.Factory(cronetEngine, Executors.newSingleThreadExecutor());
|
|
}
|
|
}
|
|
if (httpDataSourceFactory == null) {
|
|
// We don't want to use Cronet, or we failed to instantiate a CronetEngine.
|
|
CookieManager cookieManager = new CookieManager();
|
|
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
|
|
CookieHandler.setDefault(cookieManager);
|
|
httpDataSourceFactory = new DefaultHttpDataSource.Factory();
|
|
}
|
|
}
|
|
return httpDataSourceFactory;
|
|
}
|
|
|
|
/** Returns a {@link DataSource.Factory}. */
|
|
@UnstableApi
|
|
public static synchronized DataSource.Factory getDataSourceFactory(Context context) {
|
|
if (dataSourceFactory == null) {
|
|
context = context.getApplicationContext();
|
|
DefaultDataSource.Factory upstreamFactory =
|
|
new DefaultDataSource.Factory(context, getHttpDataSourceFactory(context));
|
|
dataSourceFactory = buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
|
|
}
|
|
return dataSourceFactory;
|
|
}
|
|
|
|
@UnstableApi
|
|
public static synchronized DownloadNotificationHelper getDownloadNotificationHelper(
|
|
Context context) {
|
|
if (downloadNotificationHelper == null) {
|
|
downloadNotificationHelper =
|
|
new DownloadNotificationHelper(context, DOWNLOAD_NOTIFICATION_CHANNEL_ID);
|
|
}
|
|
return downloadNotificationHelper;
|
|
}
|
|
|
|
@UnstableApi
|
|
public static synchronized DownloadManager getDownloadManager(Context context) {
|
|
ensureDownloadManagerInitialized(context);
|
|
return downloadManager;
|
|
}
|
|
|
|
@UnstableApi
|
|
public static synchronized DownloadTracker getDownloadTracker(Context context) {
|
|
ensureDownloadManagerInitialized(context);
|
|
return downloadTracker;
|
|
}
|
|
|
|
@UnstableApi
|
|
private static synchronized Cache getDownloadCache(Context context) {
|
|
if (downloadCache == null) {
|
|
File downloadContentDirectory =
|
|
new File(getDownloadDirectory(context), DOWNLOAD_CONTENT_DIRECTORY);
|
|
downloadCache =
|
|
new SimpleCache(
|
|
downloadContentDirectory, new NoOpCacheEvictor(), getDatabaseProvider(context));
|
|
}
|
|
return downloadCache;
|
|
}
|
|
|
|
@UnstableApi
|
|
private static synchronized void ensureDownloadManagerInitialized(Context context) {
|
|
if (downloadManager == null) {
|
|
downloadManager =
|
|
new DownloadManager(
|
|
context,
|
|
getDatabaseProvider(context),
|
|
getDownloadCache(context),
|
|
getHttpDataSourceFactory(context),
|
|
Executors.newFixedThreadPool(/* nThreads= */ 6));
|
|
downloadTracker =
|
|
new DownloadTracker(context, getHttpDataSourceFactory(context), downloadManager);
|
|
}
|
|
}
|
|
|
|
@UnstableApi
|
|
private static synchronized DatabaseProvider getDatabaseProvider(Context context) {
|
|
if (databaseProvider == null) {
|
|
databaseProvider = new StandaloneDatabaseProvider(context);
|
|
}
|
|
return databaseProvider;
|
|
}
|
|
|
|
private static synchronized File getDownloadDirectory(Context context) {
|
|
if (downloadDirectory == null) {
|
|
downloadDirectory = context.getExternalFilesDir(/* type= */ null);
|
|
if (downloadDirectory == null) {
|
|
downloadDirectory = context.getFilesDir();
|
|
}
|
|
}
|
|
return downloadDirectory;
|
|
}
|
|
|
|
@UnstableApi
|
|
private static CacheDataSource.Factory buildReadOnlyCacheDataSource(
|
|
DataSource.Factory upstreamFactory, Cache cache) {
|
|
return new CacheDataSource.Factory()
|
|
.setCache(cache)
|
|
.setUpstreamDataSourceFactory(upstreamFactory)
|
|
.setCacheWriteDataSinkFactory(null)
|
|
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
|
}
|
|
|
|
private DemoUtil() {}
|
|
}
|