【问题标题】:ExoPlayer2 - How to release from fragmentExoPlayer2 - 如何从片段中释放
【发布时间】:2017-07-05 20:32:41
【问题描述】:

我有一个包含 2 个片段(不是 ViewPager)的活动,并且想在其中一个片段中使用 ExoPlayer2 来播放内容。初始片段显示内容列表,单击时显示第二个片段以播放所选内容。但是,当我单击返回初始片段时,我仍然可以听到播放的内容;就好像第二个片段仍然打开一样。我正在(试图)以这种方式释放播放器:

@Override
public void onStop() {
    super.onStop();
    releasePlayer();
}

public void releasePlayer() {

    if (player != null) {
        player.setPlayWhenReady(true);
        player.stop();
        player.release();
        player = null;
        trackSelector = null;
        simpleExoPlayerView.setPlayer(null);
        simpleExoPlayerView = null;
        System.out.println("releasePlayer");
    }
}

我阅读了this,但它并没有提供太多解决方案。此外,阅读几篇在 ViewPager 片段中使用 ExoPlayer 的帖子,但不确定这些示例是如何释放播放器的。按照演示应用程序中的 releasePlayer() 方法找到 here 但没有运气。从 onPause()、onDetach()、onDestroyView() 调用 releasePlayer() 但没有区别。

这是在将侦听器添加到播放器后设置的一些日志记录,但看不到任何解释为什么它不释放的内容...

07-05 19:01:07.216 2529-2643/? V/RenderScript: 0xe0494000 Launching thread(s), CPUs 4
07-05 19:01:11.871 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:11.876 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onTimelineChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onLoadingChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onTimelineChanged...
07-05 19:01:11.904 3064-3064/? V/MediaCodecInfo: Listener-onLoadingChanged...
07-05 19:01:12.467 3064-3064/? V/MediaCodecInfo: Listener-onTimelineChanged...
07-05 19:01:12.468 3064-3064/? V/MediaCodecInfo: Listener-onTimelineChanged...
07-05 19:01:12.515 3064-3099/? V/SoftFFmpegVideo: got OMX_IndexParamPortDefinition, width: 320, height: 180
07-05 19:01:12.708 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:12.708 3064-3064/? V/MediaCodecInfo: Listener-onPlayerStateChanged...
07-05 19:01:13.380 3064-3064/? V/MediaCodecInfo: Listener-onLoadingChanged...
07-05 19:01:13.655 3064-3064/? V/MediaCodecInfo: Listener-onLoadingChanged...
07-05 19:01:18.528 3064-3099/? V/SoftFFmpegVideo: ~SoftFFmpegVideo

尝试点击按钮,但失败了

fragmentExoBinding.button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            System.out.println("button click");
            releasePlayer();
        }
    });

每次我关闭它(使用后按、主页或最近)时它都会崩溃 b/c 不再有播放器。用 if (player != null) 更新了 releasePlayer() 方法,但即使在按钮单击后仍能听到播放的内容。

【问题讨论】:

  • 如果你打电话给releasePlayer();那么super.onStop();会发生什么?
  • 感谢@Martin,但没什么区别,即使我回到了初始片段,仍然可以听到音频
  • 没有其他日志?我有一段时间没用过 exoplayer,但我记得它有一个状态机,而且大多数东西都是异步的(因为它主要是用 java 包装的原生 c++ 代码)。
  • @Martin 查看我的编辑
  • 没什么相关的……我唯一的建议是使用空白应用程序“重新开始”,并尝试使示例工作。如果一个超级简单的 2 片段示例有效,那么您可以从那里获取它。您是否“单击”后退按钮?你重写了吗?你在做一个popBackstack吗? (只是想想想谁可能会保留一个硬性参考......)顺便说一句,我想你也会想在 onStop 中做if (player != null),但这无关紧要。

标签: android android-fragments exoplayer2.x


【解决方案1】:

我在 Activity 中使用 ExoPlayer,我使用的是两步过程。 onPause我正在停止播放:

private SimpleExoPlayer player;     
@Override
protected void onPause() {
    super.onPause();

    // Pause video if it's playing
    if (isVideoPlaying()) {
        if (player != null)
            player.setPlayWhenReady(false);
    }
}

还有onDestroy我放开播放器

@Override
protected void onDestroy() {
    releasePlayer();
    super.onDestroy();
}

private void releasePlayer() {
        if (player != null) {
            player.stop();
            player.release();
            player = null;
        }
    }

【讨论】:

  • 谢谢@Kirk_hehe。我之前曾成功使用过一个活动,但尝试将应用程序从多个活动更新为具有多个片段的单个活动。
【解决方案2】:

我有一个理论,但我不确定。为了避免写超过 9000 cmets,我会发布它是一个答案。

  1. 如果您在布局中添加<Button>onClick() 调用releasePlayer();,播放器是否会停止(并被释放)?

  2. 1234563如果您想取悦 Java 人员并假装有一天您将对其进行单元测试,您可以让您的片段实现一些接口……或者您可以公开该方法并将其强制转换为您的片段并花费 5 秒而不是浪费 5 分钟和 16kb内存:)

不管怎样,接口示例:

public interface BackHandlerListener {
    void onBackPressed();
}

然后有你的片段......

class MyFragment extends Fragment implements BackHandlerListener {
    @Override
    public void onBackPressed() {
        releasePlayer();
    }
}

还有你的活动……

    @Override
    public void onBackPressed() {
        // get your fragment’s instance
        Fragment fragment =
         getSupportFragmentManager() 
            .findFragmentById(R.id.your_fragment_container);

        if (fragment instanceof BackHandlerListener) {
            ((BackHandlerListener) fragment).onBackPressed();
        }

        super.onBackPressed();
    }

你得到了演习。

  1. 如果 #1 不起作用,那么您的播放器就会发生一些奇怪的事情,它拒绝停止,但似乎与 Fragment 的生命周期有些无关。 (*)

(*) 除非问题是当片段停止并且引用泄露时媒体播放器正在死机(因为它是本机代码)。如果是这种情况,恐怕我必须阅读更多关于 ExoPlayer2 这些天是如何工作的(上次我使用媒体播放器时,ExoPlayer1 是一个“测试版”的东西,承诺会有更好的体验,但不适用于所有设备)。在那些日子里,我不得不使用 Android 服务来保持 MediaPlayer 并播放并将广播意图发送到我的服务来命令它。 ¯_(ツ)_/¯

【讨论】:

  • 老实说,此时我必须自己使用 ExoPlayer 构建一个应用程序来测试它。如果你有一个带有片段的工作演示,请联系我,我会在工作允许的某个时候看看 (*) :)
【解决方案3】:

您的问题表明您的Fragment 中的onStop() 未被调用。

您不是在两个屏幕上使用相同的Fragment 对象还是在其他地方创建另一个不必要的实例?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多