Allow play/pausing from notification when buffering

This change is in line with a recent change in how the play/pause button behaves in the player ui: if the buffering indicator is shown, it's still possible to toggle play/pause, to allow e.g. pausing videos before they even start.
This change was needed because on Android 13+ notification actions can't be null, and thus the buffering hourglass action wasn't shown.
This commit is contained in:
Stypox 2023-12-29 15:13:18 +01:00
parent 17e88f1749
commit 4b1824e8c1
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
3 changed files with 15 additions and 21 deletions

View File

@ -40,12 +40,8 @@ public class SessionConnectorActionProvider implements MediaSessionConnector.Cus
@Nullable @Nullable
@Override @Override
public PlaybackStateCompat.CustomAction getCustomAction(@NonNull final Player player) { public PlaybackStateCompat.CustomAction getCustomAction(@NonNull final Player player) {
if (data.action() == null) { return new PlaybackStateCompat.CustomAction.Builder(
return null; data.action(), data.name(), data.icon()
} else { ).build();
return new PlaybackStateCompat.CustomAction.Builder(
data.action(), data.name(), data.icon()
).build();
}
} }
} }

View File

@ -11,6 +11,7 @@ import static org.schabi.newpipe.player.notification.NotificationConstants.ACTIO
import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_REPEAT; import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_REPEAT;
import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_SHUFFLE; import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_SHUFFLE;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
@ -23,21 +24,23 @@ import org.schabi.newpipe.player.Player;
import java.util.Objects; import java.util.Objects;
public final class NotificationActionData { public final class NotificationActionData {
@Nullable
@NonNull
private final String action; private final String action;
@NonNull @NonNull
private final String name; private final String name;
@DrawableRes @DrawableRes
private final int icon; private final int icon;
public NotificationActionData(@Nullable final String action, @NonNull final String name,
public NotificationActionData(@NonNull final String action, @NonNull final String name,
@DrawableRes final int icon) { @DrawableRes final int icon) {
this.action = action; this.action = action;
this.name = name; this.name = name;
this.icon = icon; this.icon = icon;
} }
@Nullable @NonNull
public String action() { public String action() {
return action; return action;
} }
@ -52,6 +55,8 @@ public final class NotificationActionData {
return icon; return icon;
} }
@SuppressLint("PrivateResource") // we currently use Exoplayer's internal strings and icons
@Nullable @Nullable
public static NotificationActionData fromNotificationActionEnum( public static NotificationActionData fromNotificationActionEnum(
@NonNull final Player player, @NonNull final Player player,
@ -105,8 +110,7 @@ public final class NotificationActionData {
if (player.getCurrentState() == Player.STATE_PREFLIGHT if (player.getCurrentState() == Player.STATE_PREFLIGHT
|| player.getCurrentState() == Player.STATE_BLOCKED || player.getCurrentState() == Player.STATE_BLOCKED
|| player.getCurrentState() == Player.STATE_BUFFERING) { || player.getCurrentState() == Player.STATE_BUFFERING) {
// null intent action -> show hourglass icon that does nothing when clicked return new NotificationActionData(ACTION_PLAY_PAUSE,
return new NotificationActionData(null,
ctx.getString(R.string.notification_action_buffering), ctx.getString(R.string.notification_action_buffering),
R.drawable.ic_hourglass_top); R.drawable.ic_hourglass_top);
} }
@ -171,7 +175,7 @@ public final class NotificationActionData {
@Override @Override
public boolean equals(@Nullable final Object obj) { public boolean equals(@Nullable final Object obj) {
return (obj instanceof NotificationActionData other) return (obj instanceof NotificationActionData other)
&& Objects.equals(this.action, other.action) && this.action.equals(other.action)
&& this.name.equals(other.name) && this.name.equals(other.name)
&& this.icon == other.icon; && this.icon == other.icon;
} }

View File

@ -244,14 +244,8 @@ public final class NotificationUtil {
return; return;
} }
final PendingIntent intent; final PendingIntent intent = PendingIntentCompat.getBroadcast(player.getContext(),
if (data.action() == null) { NOTIFICATION_ID, new Intent(data.action()), FLAG_UPDATE_CURRENT, false);
intent = null;
} else {
intent = PendingIntentCompat.getBroadcast(player.getContext(), NOTIFICATION_ID,
new Intent(data.action()), FLAG_UPDATE_CURRENT, false);
}
builder.addAction(new NotificationCompat.Action(data.icon(), data.name(), intent)); builder.addAction(new NotificationCompat.Action(data.icon(), data.name(), intent));
} }