ExoPlayer2 - Как освободить от фрагмента

У меня есть одно действие с двумя фрагментами (не 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");
    }
}

Я прочитал это, но он не дал большого решения. Кроме того, прочитайте несколько сообщений, в которых ExoPlayer используется во фрагментах ViewPager, но не совсем уверены, как эти примеры выпустили плеер. Следуя методу releasePlayer () из демонстрационного приложения, мы нашли здесь, но безуспешно. Вызывается releasePlayer () из onPause (), onDetach (), onDestroyView (), но это не имело значения.

Вот некоторые настройки ведения журнала после того, как слушатель добавлен в проигрыватель, но я не вижу ничего, чтобы объяснить, почему он не выпускается ...

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

Он вылетал каждый раз, когда я его выключал (используя обратное нажатие, домой или недавнее), потому что игрока больше нет. Обновлен метод releasePlayer (), добавив if (player! = Null), но по-прежнему можно слышать воспроизведение содержимого даже после нажатия кнопки.


person JC23    schedule 05.07.2017    source источник
comment
Что произойдет, если вы позвоните releasePlayer(); и then super.onStop();?   -  person Martin Marconcini    schedule 05.07.2017
comment
Спасибо @Martin, но без разницы, звук все еще слышен, хотя я вернулся к исходному фрагменту   -  person JC23    schedule 06.07.2017
comment
Нет другого журнала? Я давно не использовал exoplayer, но помню, что у него был конечный автомат, а что нет, и большинство вещей было асинхронным (из-за того, что это в основном нативный код C ++, завернутый в java).   -  person Martin Marconcini    schedule 06.07.2017
comment
@ Мартин, посмотри мое редактирование   -  person JC23    schedule 06.07.2017
comment
ничего важного ... мое единственное предложение - «начать все сначала» с пустым приложением и попытаться заставить образец работать. Если супер простой образец из двух фрагментов работает, то вы можете взять его оттуда. Вы «нажимаете» кнопку «Назад»? Вы отменили назад? Вы делаете popBackstack? (просто пытаюсь подумать, кто, возможно, хранит твердую ссылку…) Между прочим, я думаю, вы тоже захотите сделать if (player != null) в onStop, но это не имеет значения.   -  person Martin Marconcini    schedule 06.07.2017
comment
Спасибо за все ваши отзывы @Martin. А пока я остановлюсь на этом, метод releasePlayer () из демонстрационного приложения работает нормально, но игрок находится в действии, а не во фрагменте. Думаю, я пойду по этому пути, если не смогу его решить. Просто нажмите кнопку «Назад», без переопределения или чего-то необычного.   -  person JC23    schedule 06.07.2017


Ответы (3)


Я использую ExoPlayer внутри Activity и использую двухэтапный процесс. 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;
        }
    }
person Kirk_hehe    schedule 06.07.2017
comment
Спасибо @Kirk_hehe. Раньше я успешно использовал действие, но пытался обновить приложение с нескольких действий до одного действия с несколькими фрагментами. - person JC23; 06.07.2017

У меня есть теория, но я не уверен. Чтобы не писать более 9000 комментариев, я отправлю это как ответ.

  1. Останавливается ли проигрыватель (и освобождается ли он), если вы добавляете <Button> в свой макет и onClick() вызываете releasePlayer();?

  2. Если вышеперечисленное работает, переопределите onBackPressed() своего действия и перед вызовом super.onBackPressed() получите экземпляр фрагмента и вызовите releasePlayer(). Вы можете сделать так, чтобы ваш фрагмент реализовал какой-то интерфейс, если вы хотите угодить Java-людям и притвориться, что однажды вы проведете модульное тестирование этого ... или вы можете сделать метод общедоступным и применить его к своему фрагменту и потратить 5 секунд вместо того, чтобы тратить 5 минут и 16 КБ объем памяти :)

Во всяком случае, пример интерфейса:

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 не сработал, то с вашим проигрывателем происходит что-то странное, что отказывается останавливаться, но, похоже, несколько не связано с жизненным циклом фрагмента. (*)

(*) Если проблема не в том, что медиаплеер умирает при остановке фрагмента и утечке ссылки (потому что это собственный код). Если это так, боюсь, мне придется больше узнать о том, как работает ExoPlayer2 в наши дни (в прошлый раз, когда я использовал медиаплеер, ExoPlayer1 был «бета-версией», обещал лучший опыт , но не на всех устройствах). В те дни мне приходилось использовать службу Android, чтобы MediaPlayer оставался и воспроизводился, а также отправлял намерения вещания в мою службу, чтобы управлять им. ¯_ (ツ) _ / ¯

person Martin Marconcini    schedule 06.07.2017
comment
Честно говоря, на данном этапе мне пришлось бы самому создать приложение с ExoPlayer, чтобы его протестировать. Если у вас есть рабочая демонстрация с фрагментами, позвоните мне, и я посмотрю (*) когда-нибудь, когда работа позволит :) - person Martin Marconcini; 10.07.2017

Ваш вопрос говорит о том, что onStop() из ваших Fragment не вызывается.

Вы не используете один и тот же объект Fragment для обоих экранов или создаете другой ненужный экземпляр где-то еще?

person Maciej Beimcik    schedule 11.05.2018