0

如果我们打开我们的应用程序,就会加载新闻片段并且新闻会自动开始播放。我们正在使用 Exoplayer 播放新闻。通知由 Exoplayer 通过 PlayerNotificationManager 创建。问题是播放暂停按钮不跟随通知。我们已经实现了事件总线,它只改变了可绘制对象。因此,如果我们单击通知上的暂停按钮,片段上的按钮被视为已暂停,但当我们单击它时,它会用作暂停按钮(而不是用作播放按钮)。

我们打算做的是:如果通知说暂停,片段上的按钮将被暂停,然后如果我们点击它,内容将开始播放。

代码:

NewsReaderFragment.java

     public static NewsReaderFragment newInstance() {
        return new NewsReaderFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_news_reader, container, false);
        bPlay = rootView.findViewById(R.id.button_play);
        unbinder = ButterKnife.bind(this, rootView);
        NetworkInfoUtility networkInfoUtility = new NetworkInfoUtility();
        boolean net = networkInfoUtility.isNetWorkAvailableNow(getContext());
        if (!net) {
            Toast.makeText(getContext(), CHECKNET, Toast.LENGTH_LONG).show();
        }
        exoHelper = new ExoHelper(getContext(), new Player.EventListener() {
            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Crashlytics.logException(error);
                Toast.makeText(getContext(), rootView.getContext().getString(R.string.server_off), Toast.LENGTH_LONG).show();
                exoHelper.ToggleButton(false);
            }
        }, bPlay, "NewsReader");

        isPlaying = true;
        setButton();
        exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));

        return rootView;
    }

    private void setButton() {
        bPlay.setOnClickListener(view -> {

            if (!isPlaying) {
                exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
            } else {
                exoHelper.stopExo();
            }

            isPlaying = !isPlaying;
        });

    } 

 @Override
    public void onStart() {
        super.onStart();

        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        
        EventBus.getDefault().unregister(this);
        super.onStop();
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(ButtonEvent event)
    {

      exoHelper.ToggleButton(event.isState());

    }

Exophelper.java

    public void stopExo() {
        if (exoPlayer != null) { //if exo is running
            Log.d(TAG, "Stopping exo....");
            exoPlayer.stop();
            //playerNotificationManager.setPlayer(null);
            customPlayerNotificationManager.setPlayer(null);
            exoPlayer.release();
            exoPlayer = null;
            ToggleButton(false);

        } else {
            Log.d(TAG, "Can't stop because No exoplayer is running");
        }
    }

    public void startExo(String newUrl) {
        if (newUrl == null || newUrl.isEmpty()) {
            Log.d(TAG, "startExo: empty url");
            Toast.makeText(context, R.string.server_off, Toast.LENGTH_SHORT).show();
            ToggleButton(false); // show pause button
            return;
        }

        if (exoPlayer != null) {
            Log.d(TAG, "startExo: Exo is already running now");
            return;
        }

        iceURL = newUrl;

        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        TrackSelection.Factory trackSelectionFactory =
                new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector defaultTrackSelector =
                new DefaultTrackSelector(trackSelectionFactory);
        DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
                context,
                Util.getUserAgent(context, context.getApplicationInfo().name),
                defaultBandwidthMeter);

        MediaSource mediaSource = new ExtractorMediaSource(
                Uri.parse(iceURL),
                dataSourceFactory,
                extractorsFactory,
                new Handler(), error -> {
        });

        exoPlayer = ExoPlayerFactory.newSimpleInstance(context, defaultTrackSelector);

        if (eventListener != null) {
            exoPlayer.addListener(eventListener);
        }
        exoPlayer.prepare(mediaSource);
        exoPlayer.setPlayWhenReady(true);

        //EventStatus(true);
          ToggleButton(true);
        //setPlayerNotificationManager(exoPlayer);
        createCustomPlayerNotificationManger(exoPlayer);


    }

public void ToggleButton(boolean state) {
        if (state) {
            Drawable img = button.getContext().getResources().getDrawable(R.drawable.play_button);
            button.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
            button.setText(R.string.now_playing);
        } else {
            Drawable img1 = button.getContext().getResources().getDrawable(R.drawable.pause_button);
            button.setCompoundDrawablesWithIntrinsicBounds(img1, null, null, null);
            button.setText(R.string.server_off);
        }
    }

PlayerNotificationManager.java


这是一个大文件,所以我们只附加我们使用事件总线的接收器:

public class NotificationBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Player player = PlayerNotificationManager.this.player;
        if (player == null
                || !isNotificationStarted
                || intent.getIntExtra(EXTRA_INSTANCE_ID, instanceId) != instanceId) {
            return;
        }
        String action = intent.getAction();
        if (ACTION_PLAY.equals(action)) {
            if (player.getPlaybackState() == Player.STATE_IDLE) {
                if (playbackPreparer != null) {
                    playbackPreparer.preparePlayback();
                }
            } else if (player.getPlaybackState() == Player.STATE_ENDED) {
                controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
            }
            controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true);

            EventBus.getDefault().post(new ButtonEvent(true));
            Log.d(TAG, "ButtonEvent: True");


        } else if (ACTION_PAUSE.equals(action)) {
            controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);

            if (player.getPlaybackState() == Player.STATE_READY)
            {
                EventBus.getDefault().post(new ButtonEvent(false));
                Log.d(TAG, "ButtonEvent: False");
            }


        } else if (ACTION_STOP.equals(action)) {
            controlDispatcher.dispatchStop(player, /* reset= */ true);
        } else if (ACTION_DISMISS.equals(action)) {
            stopNotification(/* dismissedByUser= */ true);
        } else if (action != null
                && customActionReceiver != null
                && customActions.containsKey(action)) {
            customActionReceiver.onCustomAction(player, action, intent);
        }
    }
}

按钮事件.java

public class ButtonEvent {

public boolean state;

public ButtonEvent(boolean state) {
    this.state = state;
}

public boolean isState() {
    return state;
}

public void setState(boolean state) {
    this.state = state;
}

}

4

1 回答 1

1

在这种情况下是否正确isPlaying,执行第二次暂停?

private void setButton() {
        bPlay.setOnClickListener(view -> {

            if (!isPlaying) {
                exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
            } else {
                exoHelper.stopExo();
            }
            isPlaying = !isPlaying;
        });
    } 

播放它的状态是否与 Fragment 而不是 ExoHelper 相关,是否有原因?

isPlaying也许这可以通过使用 exoplayers 事件监听器重新分配来轻松解决......

player.addListener(eventListener);

...

@Override
public void onIsPlayingChanged(boolean isPlaying) {
  if (isPlaying) {
      // player is playing
  } else {
      // player is paused
  }
}

更新

或者直接查询 exoplayer 的状态:

private void setButton() {
        bPlay.setOnClickListener(view -> {
            if (!isPlaying()) {
        exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
            } else {
                exoHelper.stopExo();
            }
        });
    } 

// this method might belong in ExoHelper?
private boolean isPlaying() {
    return player.getPlaybackState() == Player.STATE_READY && player.getPlayWhenReady();
}

进一步阅读https://exoplayer.dev/listening-to-player-events.html

于 2020-11-16T14:12:10.750 回答