在 Exoplayer IMA 扩展中保存和恢复广告进度

Save and restore ad progress in Exoplayer IMA extension

为了方便起见,我正在尝试使用 Exoplayer IMA extension (using tutorials 1, 2). I want to keep ad and content progress, so if app goes background or screen rotates, user continues from the point he/she was watching. You can see my code here 和下面的主要代码加载 VAST 广告。 (由于一些限制,我坚持使用 Exoplayer 库的 2.9.6 版本)

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());
        }
    }
}

问题是,当屏幕旋转时,activity 字段(如 ImaAdsLoader)变为空,并且广告和内容视频从头开始播放。我已经保存了播放器进度并且可以成功恢复它的位置,但 ImaAdsLoader 不是这种情况,因为我找不到恢复其状态的方法。我做错了什么吗?广告进度状态应如何保存和恢复?

视频播放器的一个常见模式是防止您的 activity 因方向更改而重新创建,因此您应该将这些标志添加到您的清单中。

android:configChanges="keyboardHidden|orientation|screenSize"

这也可以防止显示您的视频的表面视图也因方向改变而被破坏。