Skip to content

Commit b52af15

Browse files
committed
Implement glennguy's MediaStyle notifications daneren2005/Subsonic#914
1 parent 0a84e93 commit b52af15

File tree

2 files changed

+45
-87
lines changed

2 files changed

+45
-87
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies {
3535
implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.1.0'
3636
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
3737
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
38+
implementation "androidx.media:media:1.1.0"
3839
}
3940

4041
buildscript {

app/src/main/java/net/nullsum/audinaut/util/Notifications.java

Lines changed: 44 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
import android.content.Context;
2424
import android.content.Intent;
2525
import android.graphics.Bitmap;
26+
import android.graphics.BitmapFactory;
2627
import android.os.Build;
2728
import android.os.Handler;
2829
import android.util.Log;
2930
import android.view.KeyEvent;
30-
import android.view.View;
31-
import android.widget.RemoteViews;
3231

3332
import androidx.core.app.NotificationCompat;
33+
import androidx.media.app.NotificationCompat.MediaStyle;
3434

3535
import net.nullsum.audinaut.R;
3636
import net.nullsum.audinaut.activity.SubsonicActivity;
@@ -68,27 +68,38 @@ public static void showPlayingNotification(final Context context, final Download
6868

6969
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
7070

71-
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
72-
setupViews(expandedContentView, context, song, true, playing);
73-
74-
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
75-
setupViews(smallContentView, context, song, false, playing);
76-
7771
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
7872
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
7973
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
8074

81-
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
75+
Intent cancelIntent = new Intent("KEYCODE_MEDIA_STOP")
76+
.setComponent(new ComponentName(context, DownloadService.class))
77+
.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
78+
int[] compactActions = new int[]{0, 1, 2};
79+
MediaStyle mediaStyle = new MediaStyle()
80+
.setShowActionsInCompactView(compactActions)
81+
.setShowCancelButton(true)
82+
.setCancelButtonIntent(PendingIntent.getService(context, 0, cancelIntent, 0));
83+
84+
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
8285
.setChannelId(CHANNEL_PLAYING_ID)
8386
.setSmallIcon(R.drawable.stat_notify_playing)
8487
.setContentTitle(song.getTitle())
85-
.setContentText(song.getTitle())
88+
.setContentText(song.getArtist())
89+
.setSubText(song.getAlbum())
90+
.setTicker(song.getTitle())
8691
.setOngoing(playing)
87-
.setVisibility(Notification.VISIBILITY_PUBLIC)
88-
.setCustomContentView(smallContentView)
89-
.setCustomBigContentView(expandedContentView)
90-
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0))
91-
.setPriority(NotificationCompat.PRIORITY_LOW).build();
92+
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
93+
.setShowWhen(false)
94+
.setLargeIcon(getAlbumArt(context, song))
95+
.setStyle(mediaStyle)
96+
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0));
97+
addActions(context, builder, playing);
98+
final Notification notification = builder.build();
99+
100+
if(playing) {
101+
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
102+
}
92103

93104
playShowing = true;
94105
if (downloadForeground && downloadShowing) {
@@ -116,13 +127,7 @@ public static void showPlayingNotification(final Context context, final Download
116127
AudinautWidgetProvider.notifyInstances(context, downloadService, playing);
117128
}
118129

119-
private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing) {
120-
// Use the same text for the ticker and the expanded notification
121-
String title = song.getTitle();
122-
String arist = song.getArtist();
123-
String album = song.getAlbum();
124-
125-
// Set the album art.
130+
private static Bitmap getAlbumArt(Context context, MusicDirectory.Entry song) {
126131
try {
127132
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
128133
Bitmap bitmap = null;
@@ -131,90 +136,42 @@ private static void setupViews(RemoteViews rv, Context context, MusicDirectory.E
131136
}
132137
if (bitmap == null) {
133138
// set default album art
134-
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
139+
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
135140
} else {
136-
imageLoader.setNowPlayingSmall(bitmap);
137-
rv.setImageViewBitmap(R.id.notification_image, bitmap);
141+
return bitmap;
138142
}
139143
} catch (Exception x) {
140144
Log.w(TAG, "Failed to get notification cover art", x);
141-
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
142-
}
143-
144-
// set the text for the notifications
145-
rv.setTextViewText(R.id.notification_title, title);
146-
rv.setTextViewText(R.id.notification_artist, arist);
147-
rv.setTextViewText(R.id.notification_album, album);
148-
149-
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
150-
if (persistent) {
151-
if (expanded) {
152-
rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
153-
154-
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
155-
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
156-
} else {
157-
rv.setImageViewResource(R.id.control_previous, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
158-
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_forward);
159-
rv.setImageViewResource(R.id.control_next, R.drawable.notification_close);
160-
}
161-
} else {
162-
// Necessary for switching back since it appears to re-use the same layout
163-
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
164-
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_pause);
165-
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
145+
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
166146
}
147+
}
167148

168-
// Create actions for media buttons
149+
private static void addActions(final Context context, final NotificationCompat.Builder builder, final boolean playing) {
169150
PendingIntent pendingIntent;
170-
int previous = 0, pause, next, close = 0;
171-
if (persistent && !expanded) {
172-
pause = R.id.control_previous;
173-
next = R.id.control_pause;
174-
close = R.id.control_next;
175-
} else {
176-
previous = R.id.control_previous;
177-
pause = R.id.control_pause;
178-
next = R.id.control_next;
179-
}
180151

181-
if (persistent && close == 0 && expanded) {
182-
close = R.id.notification_close;
183-
rv.setViewVisibility(close, View.VISIBLE);
184-
}
185-
186-
if (previous > 0) {
187-
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
188-
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
189-
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
190-
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
191-
rv.setOnClickPendingIntent(previous, pendingIntent);
192-
}
152+
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
153+
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
154+
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
155+
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
156+
builder.addAction(R.drawable.notification_media_backward, "Previous", pendingIntent);
193157
if (playing) {
194158
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
195159
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
196160
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
197161
pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0);
198-
rv.setOnClickPendingIntent(pause, pendingIntent);
162+
builder.addAction(R.drawable.notification_media_pause, "Pause", pendingIntent);
199163
} else {
200-
Intent prevIntent = new Intent("KEYCODE_MEDIA_START");
201-
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
202-
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
203-
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
204-
rv.setOnClickPendingIntent(pause, pendingIntent);
164+
Intent playIntent = new Intent("KEYCODE_MEDIA_PLAY");
165+
playIntent.setComponent(new ComponentName(context, DownloadService.class));
166+
playIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
167+
pendingIntent = PendingIntent.getService(context, 0, playIntent, 0);
168+
builder.addAction(R.drawable.notification_media_start, "Play", pendingIntent);
205169
}
206170
Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
207171
nextIntent.setComponent(new ComponentName(context, DownloadService.class));
208172
nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
209173
pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
210-
rv.setOnClickPendingIntent(next, pendingIntent);
211-
if (close > 0) {
212-
Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
213-
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
214-
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
215-
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
216-
rv.setOnClickPendingIntent(close, pendingIntent);
217-
}
174+
builder.addAction(R.drawable.notification_media_forward, "Next", pendingIntent);
218175
}
219176

220177
public static void hidePlayingNotification(final Context context, final DownloadService downloadService, Handler handler) {

0 commit comments

Comments
 (0)