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
|
||||
register a purpose and detail reason for overlay views via
|
||||
`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.
|
||||
|
||||
### 2.11.7 (2020-06-29) ###
|
||||
|
@ -50,14 +50,14 @@ android {
|
||||
disable 'GoogleAppIndexingWarning','MissingTranslation','IconDensities'
|
||||
}
|
||||
|
||||
flavorDimensions "extensions"
|
||||
flavorDimensions "decoderExtensions"
|
||||
|
||||
productFlavors {
|
||||
noExtensions {
|
||||
dimension "extensions"
|
||||
noDecoderExtensions {
|
||||
dimension "decoderExtensions"
|
||||
}
|
||||
withExtensions {
|
||||
dimension "extensions"
|
||||
withDecoderExtensions {
|
||||
dimension "decoderExtensions"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,13 +72,14 @@ dependencies {
|
||||
implementation project(modulePrefix + 'library-hls')
|
||||
implementation project(modulePrefix + 'library-smoothstreaming')
|
||||
implementation project(modulePrefix + 'library-ui')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-av1')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-ffmpeg')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-flac')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-ima')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-opus')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-vp9')
|
||||
withExtensionsImplementation project(path: modulePrefix + 'extension-rtmp')
|
||||
implementation project(modulePrefix + 'extension-cronet')
|
||||
implementation project(modulePrefix + 'extension-ima')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-av1')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-ffmpeg')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-flac')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-opus')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-vp9')
|
||||
withDecoderExtensionsImplementation project(modulePrefix + 'extension-rtmp')
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.android.gms.strict-version-matcher-plugin'
|
||||
|
@ -1,7 +1,2 @@
|
||||
# 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.database.DatabaseProvider;
|
||||
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.DefaultDownloadIndex;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.ui.DownloadNotificationHelper;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
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.cache.Cache;
|
||||
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_CONTENT_DIRECTORY = "downloads";
|
||||
|
||||
protected String userAgent;
|
||||
|
||||
private HttpDataSource.Factory httpDataSourceFactory;
|
||||
private DatabaseProvider databaseProvider;
|
||||
private File downloadDirectory;
|
||||
private Cache downloadCache;
|
||||
@ -62,24 +62,26 @@ public class DemoApplication extends MultiDexApplication {
|
||||
@Override
|
||||
public void 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}. */
|
||||
public DataSource.Factory buildDataSourceFactory() {
|
||||
DefaultDataSourceFactory upstreamFactory =
|
||||
new DefaultDataSourceFactory(this, buildHttpDataSourceFactory());
|
||||
new DefaultDataSourceFactory(/* context= */ this, httpDataSourceFactory);
|
||||
return buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache());
|
||||
}
|
||||
|
||||
/** Returns a {@link HttpDataSource.Factory}. */
|
||||
public HttpDataSource.Factory buildHttpDataSourceFactory() {
|
||||
return new DefaultHttpDataSourceFactory(userAgent);
|
||||
}
|
||||
|
||||
/** Returns whether extension renderers should be used. */
|
||||
public boolean useExtensionRenderers() {
|
||||
return "withExtensions".equals(BuildConfig.FLAVOR);
|
||||
return "withDecoderExtensions".equals(BuildConfig.FLAVOR);
|
||||
}
|
||||
|
||||
public RenderersFactory buildRenderersFactory(boolean preferExtensionRenderer) {
|
||||
@ -112,7 +114,7 @@ public class DemoApplication extends MultiDexApplication {
|
||||
return downloadTracker;
|
||||
}
|
||||
|
||||
protected synchronized Cache getDownloadCache() {
|
||||
private synchronized Cache getDownloadCache() {
|
||||
if (downloadCache == null) {
|
||||
File downloadContentDirectory = new File(getDownloadDirectory(), DOWNLOAD_CONTENT_DIRECTORY);
|
||||
downloadCache =
|
||||
@ -130,10 +132,10 @@ public class DemoApplication extends MultiDexApplication {
|
||||
DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ true);
|
||||
downloadManager =
|
||||
new DownloadManager(
|
||||
this,
|
||||
/* context= */ this,
|
||||
getDatabaseProvider(),
|
||||
getDownloadCache(),
|
||||
buildHttpDataSourceFactory(),
|
||||
httpDataSourceFactory,
|
||||
Executors.newFixedThreadPool(/* nThreads= */ 6));
|
||||
downloadTracker =
|
||||
new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadManager);
|
||||
@ -171,7 +173,7 @@ public class DemoApplication extends MultiDexApplication {
|
||||
return downloadDirectory;
|
||||
}
|
||||
|
||||
protected static CacheDataSource.Factory buildReadOnlyCacheDataSource(
|
||||
private static CacheDataSource.Factory buildReadOnlyCacheDataSource(
|
||||
DataSource.Factory upstreamFactory, Cache cache) {
|
||||
return new CacheDataSource.Factory()
|
||||
.setCache(cache)
|
||||
|
@ -29,7 +29,6 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.google.android.exoplayer2.C;
|
||||
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.SimpleExoPlayer;
|
||||
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.MediaCodecUtil.DecoderQueryException;
|
||||
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.EventLogger;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
@ -447,31 +446,6 @@ public class PlayerActivity extends AppCompatActivity
|
||||
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
|
||||
|
||||
private void updateButtonVisibility() {
|
||||
@ -585,7 +559,6 @@ public class PlayerActivity extends AppCompatActivity
|
||||
|
||||
private class AdSupportProvider implements DefaultMediaSourceFactory.AdSupportProvider {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AdsLoader getAdsLoader(Uri adTagUri) {
|
||||
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.
|
||||
if (adsLoader == null) {
|
||||
adsLoader = maybeCreateAdsLoader(adTagUri);
|
||||
}
|
||||
if (adsLoader != null) {
|
||||
adsLoader.setPlayer(player);
|
||||
} else {
|
||||
showToast(R.string.ima_not_loaded);
|
||||
adsLoader = new ImaAdsLoader(/* context= */ PlayerActivity.this, adTagUri);
|
||||
}
|
||||
adsLoader.setPlayer(player);
|
||||
return adsLoader;
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,6 @@
|
||||
|
||||
<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="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
|
||||
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
|
||||
select and build one of the `withExtensions` build variants of the demo app in
|
||||
Android Studio. You can find IMA test content in the "IMA sample ad tags"
|
||||
section of the app. The demo app's `PlayerActivity` also shows how to persist
|
||||
the `ImaAdsLoader` instance and the player position when backgrounded during ad
|
||||
playback.
|
||||
You can try the IMA extension in the ExoPlayer demo app, which has test content
|
||||
in the "IMA sample ad tags" section of the sample chooser. The demo app's
|
||||
`PlayerActivity` also shows how to persist 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
|
||||
[sample ad tags]: https://developers.google.com/interactive-media-ads/docs/sdks/android/tags
|
||||
|
Loading…
x
Reference in New Issue
Block a user