Support notifications on API 26+

This commit is contained in:
Andrew Rabert 2018-02-27 21:26:35 -05:00
parent 3ae6ff3ca4
commit 2bdf230284
2 changed files with 283 additions and 263 deletions

View File

@ -16,6 +16,7 @@
package net.nullsum.audinaut.util; package net.nullsum.audinaut.util;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.ComponentName; import android.content.ComponentName;
@ -28,10 +29,7 @@ import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.TextView;
import net.nullsum.audinaut.R; import net.nullsum.audinaut.R;
import net.nullsum.audinaut.activity.SubsonicActivity; import net.nullsum.audinaut.activity.SubsonicActivity;
@ -41,51 +39,58 @@ import net.nullsum.audinaut.domain.PlayerState;
import net.nullsum.audinaut.provider.AudinautWidgetProvider; import net.nullsum.audinaut.provider.AudinautWidgetProvider;
import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.DownloadFile;
import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.DownloadService;
import net.nullsum.audinaut.view.UpdateView;
import static android.content.Context.NOTIFICATION_SERVICE;
public final class Notifications { public final class Notifications {
private static final String TAG = Notifications.class.getSimpleName(); private static final String TAG = Notifications.class.getSimpleName();
// Notification IDs.
public static final int NOTIFICATION_ID_PLAYING = 100; public static final int NOTIFICATION_ID_PLAYING = 100;
public static final int NOTIFICATION_ID_DOWNLOADING = 102; public static final int NOTIFICATION_ID_DOWNLOADING = 102;
public static final String CHANNEL_PLAYING_ID = "playback_controls";
public static final String CHANNEL_DOWNLOADING_ID = "media_download";
private static boolean playShowing = false; private static boolean playShowing = false;
private static boolean downloadShowing = false; private static boolean downloadShowing = false;
private static boolean downloadForeground = false; private static boolean downloadForeground = false;
private static boolean persistentPlayingShowing = false; private static boolean persistentPlayingShowing = false;
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) {
// Set the icon, scrolling text and timestamp if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
final Notification notification = new Notification(R.drawable.stat_notify_playing, song.getTitle(), System.currentTimeMillis()); int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(
CHANNEL_PLAYING_ID, context.getString(R.string.channel_playing_name), importance);
mChannel.setDescription(context.getString(R.string.channel_playing_description));
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(mChannel);
}
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED; final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
if(playing) {
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
}
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded); RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
setupViews(expandedContentView ,context, song, true, playing); setupViews(expandedContentView ,context, song, true, playing);
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); RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
setupViews(smallContentView, context, song, false, playing); setupViews(smallContentView, context, song, false, playing);
notification.contentView = smallContentView;
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
.setChannelId(CHANNEL_PLAYING_ID)
.setSmallIcon(R.drawable.stat_notify_playing)
.setContentTitle(song.getTitle())
.setContentText(song.getTitle())
.setOngoing(playing)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setCustomContentView(smallContentView)
.setCustomBigContentView(expandedContentView)
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0))
.setPriority(NotificationCompat.PRIORITY_LOW).build();
playShowing = true; playShowing = true;
if(downloadForeground && downloadShowing) { if(downloadForeground && downloadShowing) {
@ -107,7 +112,7 @@ public final class Notifications {
} else { } else {
playShowing = false; playShowing = false;
persistentPlayingShowing = true; persistentPlayingShowing = true;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
downloadService.stopForeground(false); downloadService.stopForeground(false);
notificationManager.notify(NOTIFICATION_ID_PLAYING, notification); notificationManager.notify(NOTIFICATION_ID_PLAYING, notification);
} }
@ -247,7 +252,7 @@ public final class Notifications {
downloadService.stopForeground(true); downloadService.stopForeground(true);
if(persistentPlayingShowing) { if(persistentPlayingShowing) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID_PLAYING); notificationManager.cancel(NOTIFICATION_ID_PLAYING);
persistentPlayingShowing = false; persistentPlayingShowing = false;
} }
@ -277,28 +282,37 @@ public final class Notifications {
currentSize = "0"; currentSize = "0";
} }
NotificationCompat.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder = new NotificationCompat.Builder(context) int importance = NotificationManager.IMPORTANCE_LOW;
.setSmallIcon(android.R.drawable.stat_sys_download) NotificationChannel mChannel = new NotificationChannel(
.setContentTitle(context.getResources().getString(R.string.download_downloading_title, size)) CHANNEL_DOWNLOADING_ID, context.getString(R.string.channel_download_name), importance);
.setContentText(context.getResources().getString(R.string.download_downloading_summary, currentDownloading)) mChannel.setDescription(context.getString(R.string.channel_download_description));
.setStyle(new NotificationCompat.BigTextStyle() NotificationManager notificationManager = (NotificationManager) context.getSystemService(
.bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize))) NOTIFICATION_SERVICE);
.setProgress(10, 5, true) notificationManager.createNotificationChannel(mChannel);
.setOngoing(true) }
.addAction(R.drawable.notification_close,
context.getResources().getString(R.string.common_cancel),
cancelPI);
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true); notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
builder.setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0));
final Notification notification = builder.build(); final Notification notification = new NotificationCompat.Builder(context, CHANNEL_DOWNLOADING_ID)
.setChannelId(CHANNEL_DOWNLOADING_ID)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle(context.getResources().getString(R.string.download_downloading_title, size))
.setContentText(context.getResources().getString(R.string.download_downloading_summary, currentDownloading))
.setOngoing(true)
.addAction(R.drawable.notification_close,
context.getResources().getString(R.string.common_cancel),
cancelPI)
.setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize)))
.setProgress(10, 5, true).build();
downloadShowing = true; downloadShowing = true;
if(playShowing) { if(playShowing) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID_DOWNLOADING, notification); notificationManager.notify(NOTIFICATION_ID_DOWNLOADING, notification);
} else { } else {
downloadForeground = true; downloadForeground = true;
@ -314,7 +328,7 @@ public final class Notifications {
public static void hideDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler) { public static void hideDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler) {
downloadShowing = false; downloadShowing = false;
if(playShowing) { if(playShowing) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING); notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING);
} else { } else {
downloadForeground = false; downloadForeground = false;

View File

@ -359,4 +359,10 @@
<item quantity="one">One song added to play queue.</item> <item quantity="one">One song added to play queue.</item>
<item quantity="other">%d songs added to play queue.</item> <item quantity="other">%d songs added to play queue.</item>
</plurals> </plurals>
<string name="channel.playing_name">Now Playing</string>
<string name="channel.playing_description">Media controls and information about the playing song.</string>
<string name="channel.download_name">Media Download</string>
<string name="channel.download_description">Displays progress for explicitly initiated downloads (ex. cache).</string>
</resources> </resources>