使用事件总线控制播放或暂停按钮



如果我们打开应用程序,就会加载新闻片段,并自动开始播放新闻。我们正在使用Exoplayer播放新闻。通知由Exoplayer通过PlayerNotificationManager创建。问题是播放暂停按钮没有跟随通知。我们已经实现了eventbus&它只会改变绘图。因此,如果我们点击通知上的暂停按钮,片段上的按钮会被视为暂停,但当我们点击它时,它会起到暂停按钮的作用(而不是播放按钮(。

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

代码:

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

ButtonEvent.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;
}

}

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

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

它是否在播放的状态与片段而不是ExoHelper有关,这有原因吗?

也许这可以通过将isPlaying重新分配给外部层事件侦听器来轻松解决。。。

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

更新

或者直接查询外部层的状态:

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

最新更新