2424import android .content .Context ;
2525import android .content .Intent ;
2626import android .graphics .Bitmap ;
27+ import android .graphics .BitmapFactory ;
2728import android .os .Build ;
2829import android .os .Handler ;
2930import android .support .v4 .app .NotificationCompat ;
31+ import android .support .v4 .media .app .NotificationCompat .MediaStyle ;
3032import android .util .Log ;
3133import android .view .KeyEvent ;
3234import android .view .View ;
4042import github .popeen .dsub .provider .DSubWidgetProvider ;
4143import github .popeen .dsub .service .DownloadFile ;
4244import github .popeen .dsub .service .DownloadService ;
45+ import github .popeen .dsub .util .compat .RemoteControlClientLP ;
4346import github .popeen .dsub .view .UpdateView ;
4447
4548public 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}
0 commit comments