google / google/ExoPlayer

Provide an option to make navigation behave like REPEAT_MODE_ALL even with REPEAT_MODE_OFF

Open
#7,221 7 comments 0 reactions 1 assignee Claimed by @marcbaechinger View on GitHub
enhancement
Dominant language
Java
Stars
21.9k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Force to show next and previous button for first and last song in notification and Lock screen controls when player.setRepeatMode(Player.REPEAT_MODE_ONE); and player.setRepeatMode(Player.REPEAT_MODE_OFF);

The normal behavior of a music player is
1) when player.setRepeatMode(Player.REPEAT_MODE_ONE); and player.setRepeatMode(Player.REPEAT_MODE_OFF); to show previous and next button to allow users to go back to the first or last song when they desire to, when either the first or last song is played

what actually happens in exoplayer notification and lock screen control
1) when user is on Last song with REPEAT_MODE_ONE or REPEAT_MODE_OFF , the next button is invisible, not allowing user to click the next button to go to the "FIRST" song
2) when user is on Last song with REPEAT_MODE_ONE or REPEAT_MODE_OFF ,the previous button is visible,but nothing happens, not allowing user to click the previous button to go to the "LAST" song

I am trying to override this WRONG process

using this code

```
public void Show notification() {
playerNotificationManager = CustomPlayerNotificationManager.createWithNotificationChannel(AudioPlayerService.this,
ConstantValues.PLAYBACK_CHANNEL_ID, R.string.app_name, R.string.app_name, ConstantValues.PLAYBACK_NOTIFICATION_ID,
new CustomPlayerNotificationManager.MediaDescriptionAdapter() {
@Override
public String getCurrentContentTitle(Player player) {
Title = SongsList.get(player.getCurrentWindowIndex())._title;
AlbumName = SongsList.get(player.getCurrentWindowIndex())._album;
SongPathway = SongsList.get(player.getCurrentWindowIndex())._path;
Album_ID = SongsList.get(player.getCurrentWindowIndex())._albumId;
MediaID = SongsList.get(player.getCurrentWindowIndex())._id;
return Title;
}

@Nullable
@Override
public PendingIntent createCurrentContentIntent(Player player) {
Intent intent = new Intent(AudioPlayerService.this, Blankact.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(AudioPlayerService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

@Nullable
@Override
public String getCurrentContentText(Player player) {
return AlbumName;
}

@Nullable
@Override
public Bitmap getCurrentLargeIcon(Player player, CustomPlayerNotificationManager.BitmapCallback
callback) {
bitmap = otherUtils.getAlbumartImage(AudioPlayerService.this, SongsList.get(player.getCurrentWindowIndex())._albumId);
return bitmap;
}
},
new CustomPlayerNotificationManager.NotificationListener() {

@Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
shouldsave = false;
Intent intent = new Intent(AudioPlayerService.this, ColseActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
stopped = "stopped";
stopForeground(true);
stopSelf();
}
@Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
startForeground(notificationId, notification);
}
}
);

playerNotificationManager.setPriority(NotificationCompat.PRIORITY_HIGH);
playerNotificationManager.setPlayer(player);
playerNotificationManager.setFastForwardIncrementMs(0);
playerNotificationManager.setRewindIncrementMs(0);
playerNotificationManager.setUseChronometer(false);
playerNotificationManager.setUsePlayPauseActions(true);
playerNotificationManager.setUseStopAction(true);
playerNotificationManager.setUseNavigationActionsInCompactView(true);
mediaSession = new MediaSessionCompat(AudioPlayerService.this, ConstantValues.MEDIA_SESSION_TAG);
mediaSession.setActive(true);
playerNotificationManager.setMediaSessionToken(mediaSession.getSessionToken());
mediaSessionConnector = new MediaSessionConnector(mediaSession);
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
return getMediaDescriptionl(SongsList, windowIndex);
}
});
mediaSessionConnector.setPlayer(player);

playerNotificationManager.setControlDispatcher(new DefaultControlDispatcher() {
@Override
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
// You can modify this code to call through to the player or not.
player.setPlayWhenReady(playWhenReady);
if (!player.isPlaying()) {
if (player.getRepeatMode() == Player.REPEAT_MODE_OFF && !player.hasNext()) {
if (player.getCurrentPosition() > (player.getDuration() - 1000)) {
playnextnow();
}
}
}
// Toast.makeText(AudioPlayerService.this, "playWhenReady ", Toast.LENGTH_SHORT).show();
// Return true if you called through to the player, and false otherwise.
return true;
}

});
}


public class CustomPlayerNotificationManager extends PlayerNotificationManager {

private Context context;
private Map actionMap2 = new HashMap<>();

public CustomPlayerNotificationManager(Context context, String channelId, int notificationId, MediaDescriptionAdapter mediaDescriptionAdapter) {
super(context, channelId, notificationId, mediaDescriptionAdapter);
}

public CustomPlayerNotificationManager(Context context, String channelId, int notificationId, MediaDescriptionAdapter mediaDescriptionAdapter, @Nullable NotificationListener notificationListener) {
super(context, channelId, notificationId, mediaDescriptionAdapter, notificationListener);
this.context = context;
}

public CustomPlayerNotificationManager(Context context, String channelId, int notificationId, MediaDescriptionAdapter mediaDescriptionAdapter, @Nullable CustomActionReceiver customActionReceiver) {
super(context, channelId, notificationId, mediaDescriptionAdapter, customActionReceiver);
}

public CustomPlayerNotificationManager(Context context, String channelId, int notificationId, MediaDescriptionAdapter mediaDescriptionAdapter, @Nullable NotificationListener notificationListener, @Nullable CustomActionReceiver customActionReceiver) {
super(context, channelId, notificationId, mediaDescriptionAdapter, notificationListener, customActionReceiver);
}

private boolean isPlaying(Player player) {
return player.getPlaybackState() != Player.STATE_ENDED
&& player.getPlaybackState() != Player.STATE_IDLE
&& player.getPlayWhenReady();
}

@Override
protected List getActions(Player player) {
boolean enablePrevious = true;
boolean enableRewind = false;
boolean enableFastForward = false;
boolean enableNext = true;
boolean useStopAction = true;
boolean useNavigationActions = true;
boolean usePlayPauseActions = true;
List stringActions = new ArrayList<>();
if (useNavigationActions && enablePrevious) {
stringActions.add(ACTION_PREVIOUS);
}
if (enableRewind) {
stringActions.add(ACTION_REWIND);
}
if (usePlayPauseActions) {
if (player.isPlaying()) {
stringActions.add(ACTION_PAUSE);
} else {
stringActions.add(ACTION_PLAY);
}
}
if (enableFastForward) {
stringActions.add(ACTION_FAST_FORWARD);
}
if (useNavigationActions && enableNext) {
stringActions.add(ACTION_NEXT);
}

if (useStopAction) {
stringActions.add(ACTION_STOP);
}
return stringActions;
}
}
```
But nothing works , can any one suggest what should I do

**What I am getting is**

![Screenshot_2020-04-12-11-02-14-035](https://user-images.githubusercontent.com/28686824/79061533-c933f280-7cae-11ea-973c-c0d883c9b388.jpeg)
![Screenshot_2020-04-12-11-11-41-857](https://user-images.githubusercontent.com/28686824/79061534-ca651f80-7cae-11ea-9e54-881afe86aaa4.jpeg)

**What I want is**
![Screenshot_2020-04-12-11-02-39-743](https://user-images.githubusercontent.com/28686824/79061538-dc46c280-7cae-11ea-9ddc-84a0096858ba.jpeg)
![Screenshot_2020-04-12-11-13-40-515](https://user-images.githubusercontent.com/28686824/79061539-dcdf5900-7cae-11ea-8a85-997c321f1d5e.jpeg)

for both Notification and Lock Screen Controls

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.