在 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 扩展中保存和恢复广告进度的主要内容,如果未能解决你的问题,请参考以下文章

带有ima扩展的android exoplayer无法在react native中自动显示广告的倒计时

Android Exoplayer,在屏幕旋转时恢复视频

在 ExoPlayer 中检测暂停/恢复

旋转到横向时的Exoplayer方向问题

使用 IMASDK、android 暂停广告?

ExoPlayer onResume() 恢复播放状态