aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2020-09-21 20:20:12 -0700
committerScott Jackson <daneren2005@gmail.com>2020-09-21 20:20:12 -0700
commitc62b800dc5438081cea0a5a7b625d7e904da16bb (patch)
treeb1f87c5ce8cc3feff66b56c77c737017af24d832 /app
parent0ff92da4cb86a807e9738f8f0a60e4224790ffd6 (diff)
parent4e539142736007e0a59e41da391f8b8bb58a0d53 (diff)
downloaddsub-c62b800dc5438081cea0a5a7b625d7e904da16bb.tar.gz
dsub-c62b800dc5438081cea0a5a7b625d7e904da16bb.tar.bz2
dsub-c62b800dc5438081cea0a5a7b625d7e904da16bb.zip
Merge branch 'avm99963-new-notifications' into edge
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java10
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Notifications.java178
-rw-r--r--app/src/main/res/drawable/ic_baseline_fast_forward_32.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_fast_rewind_32.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_pause_48.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_pause_64.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_play_arrow_48.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_play_arrow_64.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_skip_next_32.xml5
-rw-r--r--app/src/main/res/drawable/ic_baseline_skip_previous_32.xml5
-rw-r--r--app/src/main/res/values-es/strings.xml2
-rw-r--r--app/src/main/res/values-fr/strings.xml2
-rw-r--r--app/src/main/res/values/strings.xml2
-rw-r--r--app/src/main/res/xml/settings_playback.xml6
16 files changed, 182 insertions, 60 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 78351890..1edbc5e2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,6 +11,7 @@ android {
versionName '5.5.0'
setProperty("archivesBaseName", "DSub $versionName")
resConfigs "de", "es", "fr", "hu", "nl", "pt-rPT", "ru", "sv"
+ vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
index e9096900..aa9fcc66 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -1519,12 +1519,14 @@ public class DownloadService extends Service {
Util.requestAudioFocus(this, audioManager);
}
+ SharedPreferences prefs = Util.getPreferences(this);
+ boolean usingMediaStyleNotification = prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_STYLE_NOTIFICATION, true) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+
if (show) {
- Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong());
+ Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong(), usingMediaStyleNotification);
} else if (pause) {
- SharedPreferences prefs = Util.getPreferences(this);
- if(prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) {
- Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong());
+ if (prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) {
+ Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong(), usingMediaStyleNotification);
} else {
Notifications.hidePlayingNotification(this, this, handler);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Constants.java b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
index 017ba2f3..933f531f 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Constants.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
@@ -117,6 +117,7 @@ public final class Constants {
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
+ public static final String PREFERENCES_KEY_MEDIA_STYLE_NOTIFICATION = "mediaStyleNotification";
public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
index a8f7add0..35ab505d 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
@@ -43,6 +43,7 @@ import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.provider.DSubWidgetProvider;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
+import github.daneren2005.dsub.util.compat.RemoteControlClientLP;
import github.daneren2005.dsub.view.UpdateView;
public final class Notifications {
@@ -65,43 +66,89 @@ public final class Notifications {
private final static Pair<Integer, Integer> NOTIFICATION_TEXT_COLORS = new Pair<Integer, Integer>();
- public static void showPlayingNotification(final Context context, final DownloadService downloadService, final Handler handler, MusicDirectory.Entry song) {
+ public static void showPlayingNotification(final Context context, final DownloadService downloadService, final Handler handler, MusicDirectory.Entry song, boolean usingMediaStyleNotification) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
getPlayingNotificationChannel(context);
}
- // Set the icon, scrolling text and timestamp
- final Notification notification = new NotificationCompat.Builder(context)
- .setSmallIcon(R.drawable.stat_notify_playing)
- .setTicker(song.getTitle())
- .setWhen(System.currentTimeMillis())
- .setChannelId("now-playing-channel")
- .build();
+ final Notification notification;
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
- if(playing) {
- notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
- }
+
boolean remote = downloadService.isRemoteEnabled();
boolean isSingle = downloadService.isCurrentPlayingSingle();
boolean shouldFastForward = downloadService.shouldFastForward();
- if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN){
- RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
- setupViews(expandedContentView ,context, song, true, playing, remote, isSingle, shouldFastForward);
- notification.bigContentView = expandedContentView;
- notification.priority = Notification.PRIORITY_HIGH;
- }
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- notification.visibility = Notification.VISIBILITY_PUBLIC;
- if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HEADS_UP_NOTIFICATION, false) && !UpdateView.hasActiveActivity()) {
- notification.vibrate = new long[0];
+ if (usingMediaStyleNotification) {
+ RemoteControlClientLP remoteControlClient = (RemoteControlClientLP) downloadService.getRemoteControlClient();
+
+ android.support.v4.media.app.NotificationCompat.MediaStyle mediaStyle = new android.support.v4.media.app.NotificationCompat.MediaStyle()
+ .setMediaSession(remoteControlClient.getMediaSession().getSessionToken());
+
+ if (isSingle) {
+ mediaStyle.setShowActionsInCompactView(1);
+ } else {
+ mediaStyle.setShowActionsInCompactView(0, 2, 4);
+ }
+
+ NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "now-playing-channel")
+ .setSmallIcon(R.drawable.stat_notify_playing)
+ .setStyle(mediaStyle);
+
+ PendingIntent prevIntent = null;
+ PendingIntent nextIntent = null;
+ if (!isSingle) {
+ prevIntent = getMediaPendingIntent("KEYCODE_MEDIA_PREVIOUS", context);
+ nextIntent = getMediaPendingIntent("KEYCODE_MEDIA_NEXT", context);
+ }
+
+ PendingIntent rewindIntent = getMediaPendingIntent("KEYCODE_MEDIA_REWIND", context);
+ PendingIntent playIntent = getMediaPendingIntent(playing ? "KEYCODE_MEDIA_PLAY_PAUSE" : "KEYCODE_MEDIA_START", context);
+ PendingIntent forwardIntent = getMediaPendingIntent("KEYCODE_MEDIA_FAST_FORWARD", context);
+
+ if (!isSingle) {
+ notificationBuilder.addAction(R.drawable.ic_baseline_skip_previous_32, "Previous", prevIntent);
+ }
+
+ notificationBuilder.addAction(R.drawable.ic_baseline_fast_rewind_32, "Rewind", rewindIntent);
+ notificationBuilder.addAction(playing ? R.drawable.ic_baseline_pause_48 : R.drawable.ic_baseline_play_arrow_48, playing ? "Pause" : "Play", playIntent);
+ notificationBuilder.addAction(R.drawable.ic_baseline_fast_forward_32, "Forward", forwardIntent);
+
+ if (!isSingle) {
+ notificationBuilder.addAction(R.drawable.ic_baseline_skip_next_32, "Next", nextIntent);
+ }
+
+ notification = notificationBuilder.build();
+ } else {
+ // Set the icon, scrolling text and timestamp
+ notification = new NotificationCompat.Builder(context, "now-playing-channel")
+ .setSmallIcon(R.drawable.stat_notify_playing)
+ .setTicker(song.getTitle())
+ .setWhen(System.currentTimeMillis())
+ .build();
+
+ if(playing) {
+ notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
+ }
+
+ if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN){
+ RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
+ setupViews(expandedContentView, context, song, true, playing, remote, isSingle, shouldFastForward);
+ notification.bigContentView = expandedContentView;
+ notification.priority = Notification.PRIORITY_HIGH;
+ }
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ notification.visibility = Notification.VISIBILITY_PUBLIC;
+
+ if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HEADS_UP_NOTIFICATION, false) && !UpdateView.hasActiveActivity()) {
+ notification.vibrate = new long[0];
+ }
}
- }
- RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
- setupViews(smallContentView, context, song, false, playing, remote, isSingle, shouldFastForward);
- notification.contentView = smallContentView;
+ RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
+ setupViews(smallContentView, context, song, false, playing, remote, isSingle, shouldFastForward);
+ notification.contentView = smallContentView;
+ }
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
@@ -154,10 +201,52 @@ public final class Notifications {
DSubWidgetProvider.notifyInstances(context, downloadService, playing);
}
+ private static PendingIntent getMediaPendingIntent(String action, Context context) {
+ Intent intent = new Intent(action);
+ intent.setComponent(new ComponentName(context, DownloadService.class));
+
+ int keyCode = 0;
+ switch (action) {
+ case "KEYCODE_MEDIA_PREVIOUS":
+ keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+ break;
+
+ case "KEYCODE_MEDIA_REWIND":
+ keyCode = KeyEvent.KEYCODE_MEDIA_REWIND;
+ break;
+
+ case "KEYCODE_MEDIA_PLAY_PAUSE":
+ keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+ break;
+
+ case "KEYCODE_MEDIA_START":
+ keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
+ break;
+
+ case "KEYCODE_MEDIA_NEXT":
+ keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
+ break;
+
+ case "KEYCODE_MEDIA_FAST_FORWARD":
+ keyCode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
+ break;
+
+ case "KEYCODE_MEDIA_STOP":
+ keyCode = KeyEvent.KEYCODE_MEDIA_STOP;
+ break;
+ }
+
+ if (keyCode != 0) {
+ intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
+ }
+
+ return PendingIntent.getService(context, 0, intent, 0);
+ }
+
private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing, boolean remote, boolean isSingleFile, boolean shouldFastForward) {
// Use the same text for the ticker and the expanded notification
String title = song.getTitle();
- String arist = song.getArtist();
+ String artist = song.getArtist();
String album = song.getAlbum();
// Set the album art.
@@ -181,7 +270,7 @@ public final class Notifications {
// set the text for the notifications
rv.setTextViewText(R.id.notification_title, title);
- rv.setTextViewText(R.id.notification_artist, arist);
+ rv.setTextViewText(R.id.notification_artist, artist);
rv.setTextViewText(R.id.notification_album, album);
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
@@ -276,53 +365,32 @@ public final class Notifications {
PendingIntent pendingIntent;
if(previous > 0) {
- Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
- prevIntent.setComponent(new ComponentName(context, DownloadService.class));
- prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
- pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_PREVIOUS", context);
rv.setOnClickPendingIntent(previous, pendingIntent);
}
if(rewind > 0) {
- Intent rewindIntent = new Intent("KEYCODE_MEDIA_REWIND");
- rewindIntent.setComponent(new ComponentName(context, DownloadService.class));
- rewindIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND));
- pendingIntent = PendingIntent.getService(context, 0, rewindIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_REWIND", context);
rv.setOnClickPendingIntent(rewind, pendingIntent);
}
if(pause > 0) {
if(playing) {
- Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
- pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
- pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
- pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_PLAY_PAUSE", context);
rv.setOnClickPendingIntent(pause, pendingIntent);
} else {
- Intent prevIntent = new Intent("KEYCODE_MEDIA_START");
- prevIntent.setComponent(new ComponentName(context, DownloadService.class));
- prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
- pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_START", context);
rv.setOnClickPendingIntent(pause, pendingIntent);
}
}
if(next > 0) {
- Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
- nextIntent.setComponent(new ComponentName(context, DownloadService.class));
- nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
- pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_NEXT", context);
rv.setOnClickPendingIntent(next, pendingIntent);
}
if(fastForward > 0) {
- Intent fastForwardIntent = new Intent("KEYCODE_MEDIA_FAST_FORWARD");
- fastForwardIntent.setComponent(new ComponentName(context, DownloadService.class));
- fastForwardIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
- pendingIntent = PendingIntent.getService(context, 0, fastForwardIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_FAST_FORWARD", context);
rv.setOnClickPendingIntent(fastForward, pendingIntent);
}
if(close > 0) {
- Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
- prevIntent.setComponent(new ComponentName(context, DownloadService.class));
- prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
- pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
+ pendingIntent = getMediaPendingIntent("KEYCODE_MEDIA_STOP", context);
rv.setOnClickPendingIntent(close, pendingIntent);
}
}
diff --git a/app/src/main/res/drawable/ic_baseline_fast_forward_32.xml b/app/src/main/res/drawable/ic_baseline_fast_forward_32.xml
new file mode 100644
index 00000000..2ed77118
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_fast_forward_32.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_fast_rewind_32.xml b/app/src/main/res/drawable/ic_baseline_fast_rewind_32.xml
new file mode 100644
index 00000000..d2546368
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_fast_rewind_32.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_pause_48.xml b/app/src/main/res/drawable/ic_baseline_pause_48.xml
new file mode 100644
index 00000000..8d5e417e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_pause_48.xml
@@ -0,0 +1,5 @@
+<vector android:height="48dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_pause_64.xml b/app/src/main/res/drawable/ic_baseline_pause_64.xml
new file mode 100644
index 00000000..8de9e59e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_pause_64.xml
@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_play_arrow_48.xml b/app/src/main/res/drawable/ic_baseline_play_arrow_48.xml
new file mode 100644
index 00000000..c775d2c0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_play_arrow_48.xml
@@ -0,0 +1,5 @@
+<vector android:height="48dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_play_arrow_64.xml b/app/src/main/res/drawable/ic_baseline_play_arrow_64.xml
new file mode 100644
index 00000000..f42648b8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_play_arrow_64.xml
@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_skip_next_32.xml b/app/src/main/res/drawable/ic_baseline_skip_next_32.xml
new file mode 100644
index 00000000..23a02ee0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_skip_next_32.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_skip_previous_32.xml b/app/src/main/res/drawable/ic_baseline_skip_previous_32.xml
new file mode 100644
index 00000000..e01d6666
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_skip_previous_32.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
+</vector>
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index a5273a50..9076cf78 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -403,6 +403,8 @@
<string name="settings.replay_gain_type.track">Tags de pistas</string>
<string name="settings.open_to_tab">Abrir en pestaña</string>
<string name="settings.open_to_tab_summary">Abrir directamente a esta pestaña</string>
+ <string name="settings.media_style_notification">Notificaciones nativas multimedia de Android (5.0+)</string>
+ <string name="settings.media_style_notification_summary">Mostrar las notificaciones de reproducción como notificaciones de estilo multimedia nativas (solo en Android Lollipop y superior)</string>
<string name="share.expires">Expira: %s</string>
<string name="share.expires_never">Nunca expira</string>
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 5c576865..50909e1e 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -8,7 +8,7 @@
<string name="common.play_now">Jouer</string>
<string name="common.play_shuffled">Jouer au hasard</string>
<string name="common.play_next">Suivant</string>
- <string name="common.play_last">Précédent</string>
+ <string name="common.play_last">Jouer en dernier</string>
<string name="common.download">Mettre en cache</string>
<string name="common.pin">Mettre en cache permanent</string>
<string name="common.delete">Supprimer</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index be1a7bff..17e96487 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -495,6 +495,8 @@
<string name="settings.casting.dlna_casting_enabled.summary">If you are having battery drain problems on Android 7.0 try turning this off</string>
<string name="settings.rewind_interval">Rewind Interval</string>
<string name="settings.fastforward_interval">Fast Forward Interval</string>
+ <string name="settings.media_style_notification">Native Android media notification (5.0+)</string>
+ <string name="settings.media_style_notification_summary">Show playing notifications as native media style notifications (Android Lollipop+ only)</string>
<string name="shuffle.title">Shuffle By</string>
<string name="shuffle.startYear">Start Year:</string>
diff --git a/app/src/main/res/xml/settings_playback.xml b/app/src/main/res/xml/settings_playback.xml
index fb3501f0..fd6a7dda 100644
--- a/app/src/main/res/xml/settings_playback.xml
+++ b/app/src/main/res/xml/settings_playback.xml
@@ -46,6 +46,12 @@
android:key="headsUpNotification"
android:defaultValue="false"/>
+ <CheckBoxPreference
+ android:title="@string/settings.media_style_notification"
+ android:summary="@string/settings.media_style_notification_summary"
+ android:key="mediaStyleNotification"
+ android:defaultValue="true"/>
+
<ListPreference
android:title="@string/settings.song_press_action"
android:key="songPressAction"