If we open our app the news fragment is loaded and the news automatically starts to play. We are using Exoplayer for playing the news. Notification is created by Exoplayer via PlayerNotificationManager. The problem is that the play pause button doesn't follow the notification. We have implemented eventbus & it only changes the drawable. So, if we click on pause button on the notification, the button on fragment is seen as paused but when we click on it works as a pause button (instead of working as a play button).
What we intend to do is: If the notification says paused the button on fragment will be paused & then if we click on it the content will start to play.
Codes:
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
It's a big file, so we are attaching only the receiver where we use eventbus:
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;
}
}