diff --git a/app/src/main/java/com/khuttun/notificationnotes/NotesListAdapter.java b/app/src/main/java/com/khuttun/notificationnotes/NotesListAdapter.java index 12934a3..ce294ca 100644 --- a/app/src/main/java/com/khuttun/notificationnotes/NotesListAdapter.java +++ b/app/src/main/java/com/khuttun/notificationnotes/NotesListAdapter.java @@ -202,6 +202,7 @@ private void setNotification(NotificationNote n) if (PreferenceManager.getDefaultSharedPreferences(this.context).getBoolean(this.context .getString(R.string.group_notif_pref_key), false)) { + this.notificationMgr.checkNotification(n); this.notificationMgr.setGroupNotification(this.notes); } else diff --git a/app/src/main/java/com/khuttun/notificationnotes/NotificationMgr.java b/app/src/main/java/com/khuttun/notificationnotes/NotificationMgr.java index bc4a931..7d57454 100644 --- a/app/src/main/java/com/khuttun/notificationnotes/NotificationMgr.java +++ b/app/src/main/java/com/khuttun/notificationnotes/NotificationMgr.java @@ -8,7 +8,9 @@ import android.content.Intent; import android.graphics.Typeface; import android.os.Build; +import android.os.Bundle; import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; import android.text.Spannable; import android.text.SpannableString; import android.text.style.StyleSpan; @@ -23,17 +25,22 @@ public class NotificationMgr { private static final String CHANNEL_ID = "notes"; private static final int GROUP_NOTIF_ID = -1000; - + private static final int SUMMARY_NOTIF_ID = -2000; + private static final String GROUP_KEY = "com.khuttun.notificationnotes"; private Context context; private NotificationManager notificationManager; + private boolean groupAPI = false; private NotificationCompat.Builder notificationBuilder; public NotificationMgr(Context context) { this.context = context; + // Need the NotificationManager type for a NotificationChannel, + // the official documentation saying to use NotificationManager.Compat is + // wrong this.notificationManager = (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE); - // NotificationChannel is required on Oreo and newer + // A NotificationChannel is needed for Android Oreo and above if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { this.notificationManager.createNotificationChannel(new NotificationChannel( @@ -42,17 +49,35 @@ public NotificationMgr(Context context) NotificationManager.IMPORTANCE_LOW)); } - this.notificationBuilder = new NotificationCompat.Builder(this.context, CHANNEL_ID); - this.notificationBuilder.setSmallIcon(R.drawable.pen); - this.notificationBuilder.setOngoing(true); - this.notificationBuilder.setPriority(NotificationCompat.PRIORITY_LOW); - this.notificationBuilder.setContentIntent(PendingIntent + // Grouping notifications together so they are expandable is available on Nougat and newer + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + this.groupAPI = true; + } + + notificationBuilder = new NotificationCompat.Builder(this.context, CHANNEL_ID); + notificationBuilder.setSmallIcon(R.drawable.pen); + notificationBuilder.setOngoing(true); + notificationBuilder.setPriority(NotificationCompat.PRIORITY_LOW); + notificationBuilder.setContentIntent(PendingIntent .getActivity(this.context, 0, new Intent(this.context, MainActivity.class), 0)); } + /** + * Used for group mode to check if a notification that is + * currently being displayed needs to be canceled + */ + public void checkNotification(NotificationNote note) + { + if (!note.isVisible) + { + this.notificationManager.cancel(note.id); + } + } public void setNotification(NotificationNote note) { if (Globals.LOG) Log.d(Globals.TAG, "Notification: ID " + note.id + ", show " + note.isVisible); + if (note.isVisible) { this.notificationManager.notify(note.id, createNotification(note.title, note.text)); @@ -65,16 +90,7 @@ public void setNotification(NotificationNote note) public void setGroupNotification(ArrayList notes) { - ArrayList visibleNotes = new ArrayList<>(); - for (int i = 0; i < notes.size(); ++i) - { - NotificationNote n = notes.get(i); - if (n.isVisible) - { - visibleNotes.add(n); - } - } - + ArrayList visibleNotes = getVisibleNotes(notes); if (Globals.LOG) Log.d(Globals.TAG, "Group notification: visible notes " + visibleNotes.size()); switch (visibleNotes.size()) @@ -90,11 +106,33 @@ public void setGroupNotification(ArrayList notes) break; default: - this.notificationManager.notify(GROUP_NOTIF_ID, createGroupNotification(visibleNotes)); + if (groupAPI) + { + displayGroupNotifications(visibleNotes); + } + else + { + this.notificationManager.notify(SUMMARY_NOTIF_ID, + createSummaryNotification(visibleNotes)); + } break; } } + private static ArrayList getVisibleNotes(ArrayList notes) + { + ArrayList visibleNotes = new ArrayList<>(); + for (int i = 0; i < notes.size(); i++) + { + NotificationNote n = notes.get(i); + if (n.isVisible) + { + visibleNotes.add(n); + } + } + return visibleNotes; + } + public void clearAllNotifications() { if (Globals.LOG) Log.d(Globals.TAG, "Clearing all notifications"); @@ -109,7 +147,12 @@ private Notification createNotification(String title, String text) return this.notificationBuilder.build(); } - private Notification createGroupNotification(ArrayList notes) + /** + * Creates a notification with the number of notes and the first line of each note. + * This notification is shown for Android Versions below Nougat, and is still necessary + * for Android Nougat, but is not shown. + */ + private Notification createSummaryNotification(ArrayList notes) { NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle(); for (int i = 0; i < notes.size(); ++i) @@ -120,6 +163,8 @@ private Notification createGroupNotification(ArrayList notes) this.notificationBuilder.setContentTitle( this.context.getString(R.string.group_notif_title) + ": " + notes.size()); this.notificationBuilder.setContentText(getGroupNotificationLine(notes.get(0))); + this.notificationBuilder.setGroup(GROUP_KEY); + this.notificationBuilder.setGroupSummary(true); return this.notificationBuilder.build(); } @@ -129,4 +174,33 @@ private CharSequence getGroupNotificationLine(NotificationNote note) sp.setSpan(new StyleSpan(Typeface.BOLD), 0, note.title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return sp; } + + private void displayGroupNotifications(ArrayList visibleNotes) + { + int visibleSize = visibleNotes.size(); + for (int i = 0; i < visibleSize; i++) + { + NotificationNote note = visibleNotes.get(i); + if (Globals.LOG) + { + Log.d(Globals.TAG, "Displaying notification for note with id ".concat(Integer.toString(note.id))); + } + this.notificationManager.notify(note.id, createGroupNotification(note)); + } + this.notificationManager.notify(SUMMARY_NOTIF_ID, createSummaryNotification(visibleNotes)); + } + + /** + * Creates a notification that is the member of a group & is not the summary. + */ + private Notification createGroupNotification(NotificationNote note) + { + this.notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(note.text)); + this.notificationBuilder.setContentTitle(note.title); + this.notificationBuilder.setContentText(note.text); + this.notificationBuilder.setGroup(this.GROUP_KEY); + this.notificationBuilder.setGroupSummary(false); + return this.notificationBuilder.build(); + } } +