Skip to content

Commit 56a44bf

Browse files
committed
Updated the notification to a medianotification based on Glennguy's work daneren2005/Subsonic#914
1 parent da8314e commit 56a44bf

22 files changed

+120
-35
lines changed

app/src/main/java/github/popeen/dsub/service/DownloadService.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ public class DownloadService extends Service {
110110
public static final String CMD_NEXT = "github.popeen.dsub.CMD_NEXT";
111111
public static final String CANCEL_DOWNLOADS = "github.popeen.dsub.CANCEL_DOWNLOADS";
112112
public static final String START_PLAY = "github.popeen.dsub.START_PLAYING";
113+
public static final String THUMBS_UP = "github.popeen.dsub.THUMBS_UP";
114+
public static final String THUMBS_DOWN = "github.popeen.dsub.THUMBS_DOWN";
113115
private static final long DEFAULT_DELAY_UPDATE_PROGRESS = 1000L;
114116
private static final double DELETE_CUTOFF = 0.84;
115117
private static final int REQUIRED_ALBUM_MATCHES = 4;
@@ -309,7 +311,7 @@ public boolean onError(MediaPlayer mediaPlayer, int what, int more) {
309311
public int onStartCommand(Intent intent, int flags, int startId) {
310312
super.onStartCommand(intent, flags, startId);
311313
lifecycleSupport.onStart(intent);
312-
if(Build.VERSION.SDK_INT >= 26 && !this.isForeground()) {
314+
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && intent.getAction() == null) {
313315
Notifications.shutGoogleUpNotification(this);
314316
}
315317
return START_NOT_STICKY;
@@ -389,10 +391,17 @@ public void onDestroy() {
389391
unregisterReceiver(audioNoisyReceiver);
390392
}
391393
mediaRouter.destroy();
392-
Notifications.hidePlayingNotification(this, this, handler);
394+
if (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)
395+
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
396+
stopForeground(android.app.Service.STOP_FOREGROUND_DETACH);
397+
} else {
398+
Notifications.hidePlayingNotification(this, this, handler);
399+
}
393400
Notifications.hideDownloadingNotification(this, this, handler);
394401
}
395-
402+
public int getDownloadListSize() {
403+
return downloadList.size();
404+
}
396405
public static void startService(Context context) {
397406
startService(context, new Intent(context, DownloadService.class));
398407
}
@@ -1120,7 +1129,11 @@ private synchronized void play(int index, boolean start, int position) {
11201129
reset();
11211130
if(index >= size && size != 0) {
11221131
setCurrentPlaying(0, false);
1123-
Notifications.hidePlayingNotification(this, this, handler);
1132+
if(Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) {
1133+
Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong());
1134+
} else {
1135+
Notifications.hidePlayingNotification(this, this, handler);
1136+
}
11241137
} else {
11251138
setCurrentPlaying(null, false);
11261139
}

app/src/main/java/github/popeen/dsub/util/Notifications.java

Lines changed: 103 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import android.content.Context;
2525
import android.content.Intent;
2626
import android.graphics.Bitmap;
27+
import android.graphics.BitmapFactory;
2728
import android.os.Build;
2829
import android.os.Handler;
2930
import android.support.v4.app.NotificationCompat;
31+
import android.support.v4.media.app.NotificationCompat.MediaStyle;
3032
import android.util.Log;
3133
import android.view.KeyEvent;
3234
import android.view.View;
@@ -40,6 +42,7 @@
4042
import github.popeen.dsub.provider.DSubWidgetProvider;
4143
import github.popeen.dsub.service.DownloadFile;
4244
import github.popeen.dsub.service.DownloadService;
45+
import github.popeen.dsub.util.compat.RemoteControlClientLP;
4346
import github.popeen.dsub.view.UpdateView;
4447

4548
public final class Notifications {
@@ -60,51 +63,56 @@ public final class Notifications {
6063
private static NotificationChannel downloadingChannel;
6164
private static NotificationChannel syncChannel;
6265

63-
private final static Pair<Integer, Integer> NOTIFICATION_TEXT_COLORS = new Pair<Integer, Integer>();
64-
6566
public static void showPlayingNotification(final Context context, final DownloadService downloadService, final Handler handler, MusicDirectory.Entry song) {
6667
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
6768
getPlayingNotificationChannel(context);
6869
}
6970

7071
// Set the icon, scrolling text and timestamp
71-
final Notification notification = new NotificationCompat.Builder(context)
72+
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
7273
.setSmallIcon(R.drawable.stat_notify_playing)
7374
.setTicker(song.getTitle())
74-
.setWhen(System.currentTimeMillis())
75+
.setSubText(song.getAlbum())
76+
.setContentTitle(song.getTitle())
77+
.setContentText(song.getArtist())
7578
.setChannelId("now-playing-channel")
76-
.build();
79+
.setShowWhen(false)
80+
.setLargeIcon(getAlbumArt(context, song));
7781

7882
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
79-
if(playing) {
80-
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
81-
}
82-
boolean remote = downloadService.isRemoteEnabled();
83-
boolean isSingle = downloadService.isCurrentPlayingSingle();
84-
boolean shouldFastForward = true;
85-
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN){
86-
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
87-
setupViews(expandedContentView ,context, song, true, playing, remote, isSingle, shouldFastForward);
88-
notification.bigContentView = expandedContentView;
89-
notification.priority = Notification.PRIORITY_HIGH;
83+
final boolean thumbs = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
84+
int[] compactActions;
85+
86+
compactActions = new int[]{0, 1, 2};
87+
addActions(context, builder, song, playing, thumbs);
88+
Intent cancelIntent = new Intent("KEYCODE_MEDIA_STOP")
89+
.setComponent(new ComponentName(context, DownloadService.class))
90+
.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
91+
MediaStyle mediaStyle = new MediaStyle()
92+
.setShowActionsInCompactView(compactActions)
93+
.setShowCancelButton(true)
94+
.setCancelButtonIntent(PendingIntent.getService(context, 0, cancelIntent, 0));
95+
96+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
97+
builder.setPriority(Notification.PRIORITY_HIGH);
9098
}
9199
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
92-
notification.visibility = Notification.VISIBILITY_PUBLIC;
93-
94-
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HEADS_UP_NOTIFICATION, false) && !UpdateView.hasActiveActivity()) {
95-
notification.vibrate = new long[0];
100+
RemoteControlClientLP remoteControlClientLP = (RemoteControlClientLP) downloadService.getRemoteControlClient();
101+
mediaStyle.setMediaSession(remoteControlClientLP.getMediaSession().getSessionToken());
102+
builder.setVisibility(Notification.VISIBILITY_PUBLIC).setColor(context.getResources().getColor(R.color.lightPrimary));
103+
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HEADS_UP_NOTIFICATION, false) && !UpdateView.hasActiveActivity()) {
104+
builder.setVibrate(new long[0]);
105+
}
106+
}
107+
builder.setStyle(mediaStyle);
108+
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
109+
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
110+
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
111+
builder.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0));
112+
final Notification notification = builder.build();
113+
if(playing) {
114+
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
96115
}
97-
}
98-
99-
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
100-
setupViews(smallContentView, context, song, false, playing, remote, isSingle, shouldFastForward);
101-
notification.contentView = smallContentView;
102-
103-
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
104-
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
105-
106-
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
107-
notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
108116

109117
playShowing = true;
110118
if(downloadForeground && downloadShowing) {
@@ -152,7 +160,61 @@ public void run() {
152160
// Update widget
153161
DSubWidgetProvider.notifyInstances(context, downloadService, playing);
154162
}
163+
private static Bitmap getAlbumArt(Context context, MusicDirectory.Entry song) {
164+
try {
165+
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
166+
Bitmap bitmap = null;
167+
if(imageLoader != null) {
168+
bitmap = imageLoader.getCachedImage(context, song, false);
169+
}
170+
if (bitmap == null) {
171+
// set default album art
172+
return BitmapFactory.decodeResource(context.getResources(),
173+
R.drawable.unknown_album_large);
174+
} else {
175+
return bitmap;
176+
}
177+
} catch (Exception x) {
178+
Log.w(TAG, "Failed to get notification cover art", x);
179+
return BitmapFactory.decodeResource(context.getResources(),
180+
R.drawable.unknown_album_large);
181+
}
182+
}
183+
184+
private static void addActions(final Context context, final NotificationCompat.Builder builder, MusicDirectory.Entry song, final boolean playing, final boolean thumbs) {
185+
PendingIntent pendingIntent;
186+
DownloadService downloadService = (DownloadService) context;
187+
boolean shouldFastForward = downloadService.shouldFastForward();
188+
int rating = song.getRating();
189+
190+
Intent rewindIntent = new Intent("KEYCODE_MEDIA_REWIND");
191+
rewindIntent.setComponent(new ComponentName(context, DownloadService.class));
192+
rewindIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND));
193+
pendingIntent = PendingIntent.getService(context, 0, rewindIntent, 0);
194+
builder.addAction(R.drawable.ic_fast_rewind, "Rewind", pendingIntent);
195+
196+
if(playing) {
197+
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
198+
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
199+
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
200+
pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0);
201+
builder.addAction(R.drawable.ic_pause, "Pause", pendingIntent);
202+
} else {
203+
Intent playIntent = new Intent("KEYCODE_MEDIA_PLAY");
204+
playIntent.setComponent(new ComponentName(context, DownloadService.class));
205+
playIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
206+
pendingIntent = PendingIntent.getService(context, 0, playIntent, 0);
207+
builder.addAction(R.drawable.ic_play_arrow, "Play", pendingIntent);
208+
}
155209

210+
if(shouldFastForward) {
211+
Intent fastForwardIntent = new Intent("KEYCODE_MEDIA_FAST_FORWARD");
212+
fastForwardIntent.setComponent(new ComponentName(context, DownloadService.class));
213+
fastForwardIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
214+
pendingIntent = PendingIntent.getService(context, 0, fastForwardIntent, 0);
215+
builder.addAction(R.drawable.ic_fast_forward, "Fast Forward", pendingIntent);
216+
}
217+
}
156218
private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing, boolean remote, boolean isSingleFile, boolean shouldFastForward) {
157219
// Use the same text for the ticker and the expanded notification
158220
String title = song.getTitle();
@@ -457,6 +519,9 @@ private static NotificationChannel getDownloadingNotificationChannel(Context con
457519
@TargetApi(Build.VERSION_CODES.O)
458520
public static void shutGoogleUpNotification(final DownloadService downloadService) {
459521
// On Android O+, service crashes if startForeground isn't called within 5 seconds of starting
522+
if (downloadService.isForeground()) {
523+
return;
524+
}
460525
getDownloadingNotificationChannel(downloadService);
461526

462527
NotificationCompat.Builder builder;
@@ -553,4 +618,11 @@ private static void stopForeground(DownloadService downloadService, boolean remo
553618
downloadService.stopForeground(removeNotification);
554619
downloadService.setIsForeground(false);
555620
}
621+
622+
@TargetApi(24)
623+
private static void stopForeground(DownloadService downloadService, int removeNotification) {
624+
downloadService.stopForeground(removeNotification);
625+
downloadService.setIsForeground(false);
626+
}
627+
556628
}
282 Bytes
Loading
311 Bytes
Loading
294 Bytes
Loading
597 Bytes
Loading
218 Bytes
Loading
233 Bytes
Loading
151 Bytes
Loading
324 Bytes
Loading

0 commit comments

Comments
 (0)