mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Depend on the IMA extension in noExtensions variant
Also use the cronet extension in the demo app. PiperOrigin-RevId: 322108530
This commit is contained in:
parent
a8b64f9530
commit
7fce04a67f
@ -250,7 +250,10 @@
|
|||||||
* Migrate to new 'friendly obstruction' IMA SDK APIs, and allow apps to
|
* Migrate to new 'friendly obstruction' IMA SDK APIs, and allow apps to
|
||||||
register a purpose and detail reason for overlay views via
|
register a purpose and detail reason for overlay views via
|
||||||
`AdsLoader.AdViewProvider`.
|
`AdsLoader.AdViewProvider`.
|
||||||
* Demo app: Retain previous position in list of samples.
|
* Demo app:
|
||||||
|
* Retain previous position in list of samples.
|
||||||
|
* Replace the `extensions` variant with `decoderExtensions` and make the
|
||||||
|
demo app use the Cronet and IMA extensions by default.
|
||||||
* Add Guava dependency.
|
* Add Guava dependency.
|
||||||
|
|
||||||
### 2.11.7 (2020-06-29) ###
|
### 2.11.7 (2020-06-29) ###
|
||||||
|
@ -50,14 +50,14 @@ android {
|
|||||||
disable 'GoogleAppIndexingWarning','MissingTranslation','IconDensities'
|
disable 'GoogleAppIndexingWarning','MissingTranslation','IconDensities'
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "extensions"
|
flavorDimensions "decoderExtensions"
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
noExtensions {
|
noDecoderExtensions {
|
||||||
dimension "extensions"
|
dimension "decoderExtensions"
|
||||||
}
|
}
|
||||||
withExtensions {
|
withDecoderExtensions {
|
||||||
dimension "extensions"
|
dimension "decoderExtensions"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,13 +72,14 @@ dependencies {
|
|||||||
implementation project(modulePrefix + 'library-hls')
|
implementation project(modulePrefix + 'library-hls')
|
||||||
implementation project(modulePrefix + 'library-smoothstreaming')
|
implementation project(modulePrefix + 'library-smoothstreaming')
|
||||||
implementation project(modulePrefix + 'library-ui')
|
implementation project(modulePrefix + 'library-ui')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-av1')
|
implementation project(modulePrefix + 'extension-cronet')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-ffmpeg')
|
implementation project(modulePrefix + 'extension-ima')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-flac')
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-av1')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-ima')
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-ffmpeg')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-opus')
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-flac')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-vp9')
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-opus')
|
||||||
withExtensionsImplementation project(path: modulePrefix + 'extension-rtmp')
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-vp9')
|
||||||
|
withDecoderExtensionsImplementation project(modulePrefix + 'extension-rtmp')
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.android.gms.strict-version-matcher-plugin'
|
apply plugin: 'com.google.android.gms.strict-version-matcher-plugin'
|
||||||
|
@ -1,7 +1,2 @@
|
|||||||
# Proguard rules specific to the main demo app.
|
# Proguard rules specific to the main demo app.
|
||||||
|
|
||||||
# Constructor accessed via reflection in PlayerActivity
|
|
||||||
-dontnote com.google.android.exoplayer2.ext.ima.ImaAdsLoader
|
|
||||||
-keepclassmembers class com.google.android.exoplayer2.ext.ima.ImaAdsLoader {
|
|
||||||
<init>(android.content.Context, android.net.Uri);
|
|
||||||
}
|
|
||||||
|
@ -20,13 +20,14 @@ import com.google.android.exoplayer2.DefaultRenderersFactory;
|
|||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.database.DatabaseProvider;
|
import com.google.android.exoplayer2.database.DatabaseProvider;
|
||||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||||
|
import com.google.android.exoplayer2.ext.cronet.CronetDataSourceFactory;
|
||||||
|
import com.google.android.exoplayer2.ext.cronet.CronetEngineWrapper;
|
||||||
import com.google.android.exoplayer2.offline.ActionFileUpgradeUtil;
|
import com.google.android.exoplayer2.offline.ActionFileUpgradeUtil;
|
||||||
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
|
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||||
import com.google.android.exoplayer2.ui.DownloadNotificationHelper;
|
import com.google.android.exoplayer2.ui.DownloadNotificationHelper;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
|
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.cache.Cache;
|
import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
||||||
@ -50,8 +51,7 @@ public class DemoApplication extends MultiDexApplication {
|
|||||||
private static final String DOWNLOAD_TRACKER_ACTION_FILE = "tracked_actions";
|
private static final String DOWNLOAD_TRACKER_ACTION_FILE = "tracked_actions";
|
||||||
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
|
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
|
||||||
|
|
||||||
protected String userAgent;
|
private HttpDataSource.Factory httpDataSourceFactory;
|
||||||
|
|
||||||
private DatabaseProvider databaseProvider;
|
private DatabaseProvider databaseProvider;
|
||||||
private File downloadDirectory;
|
private File downloadDirectory;
|
||||||
private Cache downloadCache;
|
private Cache downloadCache;
|
||||||
@ -62,24 +62,26 @@ public class DemoApplication extends MultiDexApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
|
CronetEngineWrapper cronetEngineWrapper = new CronetEngineWrapper(/* context= */ this);
|
||||||
|
String userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
|
||||||
|
httpDataSourceFactory =
|
||||||
|
new CronetDataSourceFactory(
|
||||||
|
cronetEngineWrapper,
|
||||||
|
Executors.newSingleThreadExecutor(),
|
||||||
|
/* transferListener= */ null,
|
||||||
|
userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a {@link DataSource.Factory}. */
|
/** Returns a {@link DataSource.Factory}. */
|
||||||
public DataSource.Factory buildDataSourceFactory() {
|
public DataSource.Factory buildDataSourceFactory() {
|
||||||
DefaultDataSourceFactory upstreamFactory =
|
DefaultDataSourceFactory upstreamFactory =
|
||||||
new DefaultDataSourceFactory(this, buildHttpDataSourceFactory());
|
new DefaultDataSourceFactory(/* context= */ this, httpDataSourceFactory);
|
||||||
return buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache());
|
return buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a {@link HttpDataSource.Factory}. */
|
|
||||||
public HttpDataSource.Factory buildHttpDataSourceFactory() {
|
|
||||||
return new DefaultHttpDataSourceFactory(userAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether extension renderers should be used. */
|
/** Returns whether extension renderers should be used. */
|
||||||
public boolean useExtensionRenderers() {
|
public boolean useExtensionRenderers() {
|
||||||
return "withExtensions".equals(BuildConfig.FLAVOR);
|
return "withDecoderExtensions".equals(BuildConfig.FLAVOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderersFactory buildRenderersFactory(boolean preferExtensionRenderer) {
|
public RenderersFactory buildRenderersFactory(boolean preferExtensionRenderer) {
|
||||||
@ -112,7 +114,7 @@ public class DemoApplication extends MultiDexApplication {
|
|||||||
return downloadTracker;
|
return downloadTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized Cache getDownloadCache() {
|
private synchronized Cache getDownloadCache() {
|
||||||
if (downloadCache == null) {
|
if (downloadCache == null) {
|
||||||
File downloadContentDirectory = new File(getDownloadDirectory(), DOWNLOAD_CONTENT_DIRECTORY);
|
File downloadContentDirectory = new File(getDownloadDirectory(), DOWNLOAD_CONTENT_DIRECTORY);
|
||||||
downloadCache =
|
downloadCache =
|
||||||
@ -130,10 +132,10 @@ public class DemoApplication extends MultiDexApplication {
|
|||||||
DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ true);
|
DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ true);
|
||||||
downloadManager =
|
downloadManager =
|
||||||
new DownloadManager(
|
new DownloadManager(
|
||||||
this,
|
/* context= */ this,
|
||||||
getDatabaseProvider(),
|
getDatabaseProvider(),
|
||||||
getDownloadCache(),
|
getDownloadCache(),
|
||||||
buildHttpDataSourceFactory(),
|
httpDataSourceFactory,
|
||||||
Executors.newFixedThreadPool(/* nThreads= */ 6));
|
Executors.newFixedThreadPool(/* nThreads= */ 6));
|
||||||
downloadTracker =
|
downloadTracker =
|
||||||
new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadManager);
|
new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadManager);
|
||||||
@ -171,7 +173,7 @@ public class DemoApplication extends MultiDexApplication {
|
|||||||
return downloadDirectory;
|
return downloadDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static CacheDataSource.Factory buildReadOnlyCacheDataSource(
|
private static CacheDataSource.Factory buildReadOnlyCacheDataSource(
|
||||||
DataSource.Factory upstreamFactory, Cache cache) {
|
DataSource.Factory upstreamFactory, Cache cache) {
|
||||||
return new CacheDataSource.Factory()
|
return new CacheDataSource.Factory()
|
||||||
.setCache(cache)
|
.setCache(cache)
|
||||||
|
@ -29,7 +29,6 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
@ -39,6 +38,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
|
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
||||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||||
@ -60,7 +60,6 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||||
import com.google.android.exoplayer2.util.EventLogger;
|
import com.google.android.exoplayer2.util.EventLogger;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.net.CookieHandler;
|
import java.net.CookieHandler;
|
||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
import java.net.CookiePolicy;
|
import java.net.CookiePolicy;
|
||||||
@ -447,31 +446,6 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
return ((DemoApplication) getApplication()).buildDataSourceFactory();
|
return ((DemoApplication) getApplication()).buildDataSourceFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an ads loader for the Interactive Media Ads SDK if found in the classpath, or null
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private AdsLoader maybeCreateAdsLoader(Uri adTagUri) {
|
|
||||||
// Load the extension source using reflection so the demo app doesn't have to depend on it.
|
|
||||||
try {
|
|
||||||
Class<?> loaderClass = Class.forName("com.google.android.exoplayer2.ext.ima.ImaAdsLoader");
|
|
||||||
// Full class names used so the lint rule triggers should any of the classes move.
|
|
||||||
// LINT.IfChange
|
|
||||||
Constructor<? extends AdsLoader> loaderConstructor =
|
|
||||||
loaderClass
|
|
||||||
.asSubclass(AdsLoader.class)
|
|
||||||
.getConstructor(android.content.Context.class, android.net.Uri.class);
|
|
||||||
// LINT.ThenChange(../../../../../../../../proguard-rules.txt)
|
|
||||||
return loaderConstructor.newInstance(this, adTagUri);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// IMA extension not loaded.
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// User controls
|
// User controls
|
||||||
|
|
||||||
private void updateButtonVisibility() {
|
private void updateButtonVisibility() {
|
||||||
@ -585,7 +559,6 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
|
|
||||||
private class AdSupportProvider implements DefaultMediaSourceFactory.AdSupportProvider {
|
private class AdSupportProvider implements DefaultMediaSourceFactory.AdSupportProvider {
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public AdsLoader getAdsLoader(Uri adTagUri) {
|
public AdsLoader getAdsLoader(Uri adTagUri) {
|
||||||
if (mediaItems.size() > 1) {
|
if (mediaItems.size() > 1) {
|
||||||
@ -599,13 +572,9 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
// The ads loader is reused for multiple playbacks, so that ad playback can resume.
|
// The ads loader is reused for multiple playbacks, so that ad playback can resume.
|
||||||
if (adsLoader == null) {
|
if (adsLoader == null) {
|
||||||
adsLoader = maybeCreateAdsLoader(adTagUri);
|
adsLoader = new ImaAdsLoader(/* context= */ PlayerActivity.this, adTagUri);
|
||||||
}
|
|
||||||
if (adsLoader != null) {
|
|
||||||
adsLoader.setPlayer(player);
|
|
||||||
} else {
|
|
||||||
showToast(R.string.ima_not_loaded);
|
|
||||||
}
|
}
|
||||||
|
adsLoader.setPlayer(player);
|
||||||
return adsLoader;
|
return adsLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@
|
|||||||
|
|
||||||
<string name="sample_list_load_error">One or more sample lists failed to load</string>
|
<string name="sample_list_load_error">One or more sample lists failed to load</string>
|
||||||
|
|
||||||
<string name="ima_not_loaded">Playing sample without ads, as the IMA extension was not loaded</string>
|
|
||||||
|
|
||||||
<string name="unsupported_ads_in_concatenation">Playing sample without ads, as ads are not supported in concatenations</string>
|
<string name="unsupported_ads_in_concatenation">Playing sample without ads, as ads are not supported in concatenations</string>
|
||||||
|
|
||||||
<string name="download_start_error">Failed to start download</string>
|
<string name="download_start_error">Failed to start download</string>
|
||||||
|
@ -46,12 +46,10 @@ On returning to the foreground, seek to that position before preparing the new
|
|||||||
player instance. Finally, it is important to call `ImaAdsLoader.release()` when
|
player instance. Finally, it is important to call `ImaAdsLoader.release()` when
|
||||||
playback of the content/ads has finished and will not be resumed.
|
playback of the content/ads has finished and will not be resumed.
|
||||||
|
|
||||||
You can try the IMA extension in the ExoPlayer demo app. To do this you must
|
You can try the IMA extension in the ExoPlayer demo app, which has test content
|
||||||
select and build one of the `withExtensions` build variants of the demo app in
|
in the "IMA sample ad tags" section of the sample chooser. The demo app's
|
||||||
Android Studio. You can find IMA test content in the "IMA sample ad tags"
|
`PlayerActivity` also shows how to persist the `ImaAdsLoader` instance and the
|
||||||
section of the app. The demo app's `PlayerActivity` also shows how to persist
|
player position when backgrounded during ad playback.
|
||||||
the `ImaAdsLoader` instance and the player position when backgrounded during ad
|
|
||||||
playback.
|
|
||||||
|
|
||||||
[top level README]: https://github.com/google/ExoPlayer/blob/release-v2/README.md
|
[top level README]: https://github.com/google/ExoPlayer/blob/release-v2/README.md
|
||||||
[sample ad tags]: https://developers.google.com/interactive-media-ads/docs/sdks/android/tags
|
[sample ad tags]: https://developers.google.com/interactive-media-ads/docs/sdks/android/tags
|
||||||
|
Loading…
x
Reference in New Issue
Block a user