在 Exoplayer IMA 扩展中保存和恢复广告进度
Posted
技术标签:
【中文标题】在 Exoplayer IMA 扩展中保存和恢复广告进度【英文标题】:Save and restore ad progress in Exoplayer IMA extension 【发布时间】:2020-09-23 03:42:11 【问题描述】:我正在尝试使用 Exoplayer IMA extension 加载 VAST 广告(使用教程 1、2)。我想保持广告和内容的进度,所以如果应用程序进入后台或屏幕旋转,用户会从他/她观看的地方继续。为方便起见,您可以在下面查看我的代码here 和主要代码。 (由于一些限制,我坚持使用 2.9.6 版的 Exoplayer 库)
public class MainActivity extends AppCompatActivity
private PlayerView playerView;
private SimpleExoPlayer player;
private static final String KEY_WINDOW = "window";
private int currentWindow;
private static final String KEY_POSITION = "position";
private long playbackPosition;
private static final String KEY_AUTO_PLAY = "auto_play";
private boolean playWhenReady;
private ImaAdsLoader adsLoader;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playerView = findViewById(R.id.exo_video_view);
if (adsLoader == null)
adsLoader = new ImaAdsLoader(this, Uri.parse(getString(R.string.ad_tag_url)));
if (savedInstanceState != null)
currentWindow = savedInstanceState.getInt(KEY_WINDOW);
playbackPosition = savedInstanceState.getLong(KEY_POSITION);
playWhenReady = savedInstanceState.getBoolean(KEY_AUTO_PLAY, true);
private MediaSource buildMediaSource(Uri uri, DataSource.Factory dataSourceFactory)
return new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
private MediaSource buildAdMediaSource(MediaSource contentMediaSource, DataSource.Factory dataSourceFactory)
// Create the AdsMediaSource using the AdsLoader and the MediaSource.
return new AdsMediaSource(contentMediaSource, dataSourceFactory, adsLoader, playerView);
@Override
protected void onNewIntent(Intent intent)
super.onNewIntent(intent);
private void initializePlayer()
player = ExoPlayerFactory.newSimpleInstance(this);
playerView.setPlayer(player);
if (adsLoader != null)
adsLoader.setPlayer(player);
Uri contentUri = Uri.parse(getString(R.string.media_url_mp4));
DataSource.Factory dataSourceFactory =
new DefaultDataSourceFactory(this, "exoplayer-codelab");
MediaSource contentMediaSource = buildMediaSource(contentUri, dataSourceFactory);
MediaSource adMediaSource = buildAdMediaSource(contentMediaSource, dataSourceFactory);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPosition);
player.prepare(adMediaSource, false, false);
@Override
public void onStart()
super.onStart();
if (Util.SDK_INT >= 24)
initializePlayer();
if (playerView != null)
playerView.onResume();
@Override
public void onResume()
super.onResume();
hideSystemUi();
if ((Util.SDK_INT < 24 || player == null))
initializePlayer();
if (playerView != null)
playerView.onResume();
private void hideSystemUi()
playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
@Override
public void onPause()
super.onPause();
if (Util.SDK_INT < 24)
if (playerView != null)
playerView.onPause();
releasePlayer();
@Override
public void onStop()
super.onStop();
if (Util.SDK_INT >= 24)
if (playerView != null)
playerView.onPause();
releasePlayer();
@Override
protected void onDestroy()
super.onDestroy();
releaseAdsLoader();
private void releasePlayer()
if (player != null)
updateStartPosition();
player.release();
player = null;
if (adsLoader != null)
adsLoader.setPlayer(null);
private void releaseAdsLoader()
if (adsLoader != null)
adsLoader.release();
adsLoader = null;
if (playerView.getOverlayFrameLayout() != null)
playerView.getOverlayFrameLayout().removeAllViews();
@Override
public void onSaveInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
updateStartPosition();
outState.putBoolean(KEY_AUTO_PLAY, playWhenReady);
outState.putInt(KEY_WINDOW, currentWindow);
outState.putLong(KEY_POSITION, playbackPosition);
private void updateStartPosition()
if (player != null)
playWhenReady = player.getPlayWhenReady();
currentWindow = player.getCurrentWindowIndex();
playbackPosition = Math.max(0, player.getContentPosition());
问题是,当屏幕旋转时,ImaAdsLoader
等活动字段变为空,并且广告和内容视频从头开始播放。我已经保存了玩家进度并且可以成功恢复它的位置,但ImaAdsLoader
并非如此,因为我找不到恢复其状态的方法。我做错什么了吗?应该如何保存和恢复广告进度状态?
【问题讨论】:
【参考方案1】:视频播放器的一个常见模式是防止您的活动因方向更改而重新创建,因此您应该将这些标志添加到您的清单中。
android:configChanges="keyboardHidden|orientation|screenSize"
这也可以防止显示视频的表面视图也因方向更改而被破坏。
【讨论】:
我希望有一个围绕 IMA API 的解决方案,但没有给出。我想到了两种方法;你说的那个和另一个使用 ViewModel (或类似方法)的。由于我们的代码库是一个滞后的,我们最终使用了您的方法。以上是关于在 Exoplayer IMA 扩展中保存和恢复广告进度的主要内容,如果未能解决你的问题,请参考以下文章