多个活动上的 MediaPlayer 和 SurfaceView

MediaPlayer and SurfaceView over multiple activities

我在一个 activity 上有一个媒体播放器(称为播放器),我希望能够支持从播放器关闭到父 activity 上的微型视图的连续视频播放.

当它只有音频时我可以很好地做到这一点,问题出在我通过 mediaPlayer.setDisplay();

附加 SurfaceView 时

最初我可以很好地附加 SurfaceView,但是当我关闭播放器时问题就开始了 activity。如果我不做任何更改,mediaPlayer 会以某种方式进入错误状态,并出现通常无用的错误 (1, -19) 等

我曾尝试在 Player SurfaceView 被销毁时使用 setDisplay(null),这似乎有效。但出于某种原因,它会重置视频流。我已经尝试覆盖 seekTo() 以弄清楚发生了什么,但没有调用 seekTo()。我还在我能想到的任何地方都放置了日志记录语句,但没有任何东西被触发。

为什么 setDisplay(null) 会导致我的视​​频流重新启动?

这是我当前的 MediaPlayer 代码(一些奇怪的东西来自我试图解决的问题(比如 isReallyPlaying())):

  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private ScheduledFuture beeperhandle;

    private boolean isPaused = false;
    private BaseMedia currentMedia;

    private PlaybackService.RepeatStatus repeatStatus = PlaybackService.RepeatStatus.REPEAT_NONE;

    public void startMedia(BaseMedia model, Integer position) {
        Timber.d("Starting media");
        startBeeper();
        isPaused = false;
        lastBeep = -1;
        currentMedia = model;

        if (position != null) {
            seekTo(position);
        }
        super.start();
    }

    public BaseMedia getCurrentMedia() {
        return currentMedia;
    }



    @Override
    public void start() throws IllegalStateException {
        Timber.e("Invalid start called, should request startSong or startVideo");
    }

    private int lastBeep = -1;

    // Because isPlaying is returning false and canceling the beeper.  Probably has something to do with the surfaceview being destroyed
    private boolean isStillPlaying() {
        if (lastBeep != getCurrentPosition()) {
            lastBeep = getCurrentPosition();
            return true;
        }
        return false;
    }

    private final Runnable seekBarCheck = new Runnable() {
        public void run() {

            if (isStillPlaying() && !beeperhandle.isCancelled()) {
                EventBus.getDefault().post(new MusicStatusTimeEvent(
                        currentMedia, true, GevaldMediaPlayer.this));
            } else {
                Timber.d("Canceling Beeper, !isPlaying");
                beeperhandle.cancel(true);
            }
        }
    };

    private void startBeeper() {
        Timber.d("Starting Beeper");
        beeperhandle = scheduler.scheduleAtFixedRate(seekBarCheck, 100, 100, TimeUnit.MILLISECONDS);
    }

    @Override
    public void seekTo(final int msec) throws IllegalStateException {
        Timber.d("Seeking to " + msec);
        if (beeperhandle != null) {
            Timber.d("Canceling beeper in prep for seek");
            beeperhandle.cancel(true);
        }
        setOnSeekCompleteListener(new OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mp) {
                Timber.d("Seek complete to: " + msec);
                startBeeper();
            }
        });
        super.seekTo(msec);
    }


    @Override
    public void stop() throws IllegalStateException {
        super.stop();
        Timber.d("Stopping media");
        doStop();
    }

    private void doStop() {
        if (beeperhandle != null) {
            Timber.d("Canceling beeper, doStop");
            beeperhandle.cancel(true);
        }
        isPaused = false;
    }

    @Override
    public void pause() throws IllegalStateException {
        Timber.d("Pause requested");
        if (beeperhandle != null) {
            Timber.d("Canceling beeper, pause");
            beeperhandle.cancel(true);
        }
        doStop();
        EventBus.getDefault().post(new MusicStatusStoppedEvent(this));
        super.pause();

    }

    public boolean isPaused() {
        return isPaused;
    }

想通了。显然关闭 activity 会导致音频丢失,值为 AudioManager.AUDIOFOCUS_LOSS.

因为我是一个好Android公民,所以准备发布媒体播放器。但是随后会恢复音频,这会导致我的媒体播放器重置并因此从头开始播放。

刚好排成一行,这发生在 setDisplay() 方法周围。