|
|
@ -26,7 +26,6 @@ import android.app.PendingIntent;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.media.RingtoneManager;
|
|
|
|
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Bundle;
|
|
|
@ -108,6 +107,7 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
|
|
|
|
|
|
|
|
|
|
|
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
|
|
|
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
|
|
|
import static androidx.core.app.NotificationCompat.DEFAULT_LIGHTS;
|
|
|
|
import static androidx.core.app.NotificationCompat.DEFAULT_LIGHTS;
|
|
|
|
|
|
|
|
import static androidx.core.app.NotificationCompat.DEFAULT_SOUND;
|
|
|
|
|
|
|
|
|
|
|
|
class Core {
|
|
|
|
class Core {
|
|
|
|
private static int lastUnseen = -1;
|
|
|
|
private static int lastUnseen = -1;
|
|
|
@ -1903,7 +1903,6 @@ class Core {
|
|
|
|
final List<Long> add = new ArrayList<>();
|
|
|
|
final List<Long> add = new ArrayList<>();
|
|
|
|
final List<Long> remove = groupNotifying.get(group);
|
|
|
|
final List<Long> remove = groupNotifying.get(group);
|
|
|
|
|
|
|
|
|
|
|
|
int updates = 0;
|
|
|
|
|
|
|
|
for (Notification notification : notifications) {
|
|
|
|
for (Notification notification : notifications) {
|
|
|
|
Long id = notification.extras.getLong("id", 0);
|
|
|
|
Long id = notification.extras.getLong("id", 0);
|
|
|
|
if (id != 0)
|
|
|
|
if (id != 0)
|
|
|
@ -1911,20 +1910,16 @@ class Core {
|
|
|
|
remove.remove(id);
|
|
|
|
remove.remove(id);
|
|
|
|
Log.i("Notify existing=" + id);
|
|
|
|
Log.i("Notify existing=" + id);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (remove.contains(-id)) {
|
|
|
|
remove.remove(-id);
|
|
|
|
updates++;
|
|
|
|
|
|
|
|
remove.remove(-id);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
add.add(id);
|
|
|
|
add.add(id);
|
|
|
|
Log.i("Notify adding=" + id);
|
|
|
|
Log.i("Notify adding=" + id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Log.i("Notify group=" + group + " count=" + notifications.size() +
|
|
|
|
Log.i("Notify group=" + group + " count=" + notifications.size() +
|
|
|
|
" added=" + add.size() + " removed=" + remove.size() + " updates=" + updates);
|
|
|
|
" added=" + add.size() + " removed=" + remove.size());
|
|
|
|
|
|
|
|
|
|
|
|
if (notifications.size() == 0 ||
|
|
|
|
if (notifications.size() == 0) {
|
|
|
|
(Build.VERSION.SDK_INT < Build.VERSION_CODES.O && add.size() - updates > 0)) {
|
|
|
|
|
|
|
|
String tag = "unseen." + group + "." + 0;
|
|
|
|
String tag = "unseen." + group + "." + 0;
|
|
|
|
Log.i("Notify cancel tag=" + tag);
|
|
|
|
Log.i("Notify cancel tag=" + tag);
|
|
|
|
nm.cancel(tag, 1);
|
|
|
|
nm.cancel(tag, 1);
|
|
|
@ -1975,8 +1970,8 @@ class Core {
|
|
|
|
private static List<Notification> getNotificationUnseen(Context context, String group, List<TupleMessageEx> messages) {
|
|
|
|
private static List<Notification> getNotificationUnseen(Context context, String group, List<TupleMessageEx> messages) {
|
|
|
|
List<Notification> notifications = new ArrayList<>();
|
|
|
|
List<Notification> notifications = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
// Android 7+ https://developer.android.com/training/notify-user/group
|
|
|
|
// Android 7+ N https://developer.android.com/training/notify-user/group
|
|
|
|
// Android 8+ https://developer.android.com/training/notify-user/channels
|
|
|
|
// Android 8+ O https://developer.android.com/training/notify-user/channels
|
|
|
|
|
|
|
|
|
|
|
|
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
|
|
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
|
|
if (messages == null || messages.size() == 0 || nm == null)
|
|
|
|
if (messages == null || messages.size() == 0 || nm == null)
|
|
|
@ -2001,73 +1996,62 @@ class Core {
|
|
|
|
for (TupleMessageEx message : messages)
|
|
|
|
for (TupleMessageEx message : messages)
|
|
|
|
messageContact.put(message, ContactInfo.get(context, message.from, false));
|
|
|
|
messageContact.put(message, ContactInfo.get(context, message.from, false));
|
|
|
|
|
|
|
|
|
|
|
|
// Build pending intents
|
|
|
|
// Summary notification
|
|
|
|
Intent summary = new Intent(context, ActivityView.class).setAction("unified");
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
|
PendingIntent piSummary = PendingIntent.getActivity(context, ActivityView.REQUEST_UNIFIED, summary, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
// Build pending intents
|
|
|
|
|
|
|
|
Intent summary = new Intent(context, ActivityView.class).setAction("unified");
|
|
|
|
|
|
|
|
PendingIntent piSummary = PendingIntent.getActivity(context, ActivityView.REQUEST_UNIFIED, summary, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
|
|
|
|
|
|
|
|
Intent clear = new Intent(context, ServiceUI.class).setAction("clear");
|
|
|
|
Intent clear = new Intent(context, ServiceUI.class).setAction("clear");
|
|
|
|
PendingIntent piClear = PendingIntent.getService(context, ServiceUI.PI_CLEAR, clear, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
PendingIntent piClear = PendingIntent.getService(context, ServiceUI.PI_CLEAR, clear, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
|
|
|
|
|
|
|
|
// Build title
|
|
|
|
// Build title
|
|
|
|
String title = context.getResources().getQuantityString(
|
|
|
|
String title = context.getResources().getQuantityString(
|
|
|
|
R.plurals.title_notification_unseen, messages.size(), messages.size());
|
|
|
|
R.plurals.title_notification_unseen, messages.size(), messages.size());
|
|
|
|
|
|
|
|
|
|
|
|
// Build notification
|
|
|
|
// Build notification
|
|
|
|
NotificationCompat.Builder builder =
|
|
|
|
NotificationCompat.Builder builder =
|
|
|
|
new NotificationCompat.Builder(context, "notification")
|
|
|
|
new NotificationCompat.Builder(context, "notification")
|
|
|
|
.setSmallIcon(R.drawable.baseline_email_white_24)
|
|
|
|
.setSmallIcon(R.drawable.baseline_email_white_24)
|
|
|
|
.setContentTitle(title)
|
|
|
|
.setContentTitle(title)
|
|
|
|
.setContentIntent(piSummary)
|
|
|
|
.setContentIntent(piSummary)
|
|
|
|
.setNumber(messages.size())
|
|
|
|
.setNumber(messages.size())
|
|
|
|
.setShowWhen(false)
|
|
|
|
.setShowWhen(false)
|
|
|
|
.setDeleteIntent(piClear)
|
|
|
|
.setDeleteIntent(piClear)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
|
|
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
|
|
|
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
|
|
.setGroup(group)
|
|
|
|
.setGroup(group)
|
|
|
|
.setGroupSummary(true)
|
|
|
|
.setGroupSummary(true)
|
|
|
|
.setGroupAlertBehavior(Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
|
|
|
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
|
|
|
? NotificationCompat.GROUP_ALERT_SUMMARY
|
|
|
|
|
|
|
|
: NotificationCompat.GROUP_ALERT_CHILDREN)
|
|
|
|
|
|
|
|
.setOnlyAlertOnce(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Notification pub = builder.build();
|
|
|
|
|
|
|
|
builder
|
|
|
|
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
|
|
|
|
|
|
|
|
.setPublicVersion(pub);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!biometrics) {
|
|
|
|
|
|
|
|
DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
for (EntityMessage message : messages) {
|
|
|
|
|
|
|
|
sb.append("<strong>").append(messageContact.get(message).getDisplayName(true)).append("</strong>");
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(message.subject))
|
|
|
|
|
|
|
|
sb.append(": ").append(message.subject);
|
|
|
|
|
|
|
|
sb.append(" ").append(df.format(message.received));
|
|
|
|
|
|
|
|
sb.append("<br>");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
builder.setStyle(new NotificationCompat.BigTextStyle()
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
|
|
|
.bigText(HtmlHelper.fromHtml(sb.toString()))
|
|
|
|
builder.setSound(null);
|
|
|
|
.setSummaryText(title));
|
|
|
|
|
|
|
|
}
|
|
|
|
Notification pub = builder.build();
|
|
|
|
|
|
|
|
builder
|
|
|
|
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
|
|
|
|
|
|
|
|
.setPublicVersion(pub);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!biometrics) {
|
|
|
|
|
|
|
|
DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
for (EntityMessage message : messages) {
|
|
|
|
|
|
|
|
sb.append("<strong>").append(messageContact.get(message).getDisplayName(true)).append("</strong>");
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(message.subject))
|
|
|
|
|
|
|
|
sb.append(": ").append(message.subject);
|
|
|
|
|
|
|
|
sb.append(" ").append(df.format(message.received));
|
|
|
|
|
|
|
|
sb.append("<br>");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
|
|
builder.setStyle(new NotificationCompat.BigTextStyle()
|
|
|
|
if (light) {
|
|
|
|
.bigText(HtmlHelper.fromHtml(sb.toString()))
|
|
|
|
builder.setDefaults(DEFAULT_LIGHTS);
|
|
|
|
.setSummaryText(title));
|
|
|
|
//builder.setLights(Color.WHITE, 1000, 1000);
|
|
|
|
|
|
|
|
Log.i("Notify light enabled");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Uri uri = (sound == null ? null : Uri.parse(sound));
|
|
|
|
notifications.add(builder.build());
|
|
|
|
if (uri == null || "file".equals(uri.getScheme()))
|
|
|
|
|
|
|
|
uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
|
|
|
|
|
|
|
builder.setSound(uri);
|
|
|
|
|
|
|
|
Log.i("Notify sound=" + uri);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
notifications.add(builder.build());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Message notifications
|
|
|
|
// Message notifications
|
|
|
|
for (TupleMessageEx message : messages) {
|
|
|
|
for (TupleMessageEx message : messages) {
|
|
|
|
ContactInfo info = messageContact.get(message);
|
|
|
|
ContactInfo info = messageContact.get(message);
|
|
|
@ -2118,13 +2102,35 @@ class Core {
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
|
|
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
|
|
|
|
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
|
|
|
|
.setGroup(group)
|
|
|
|
|
|
|
|
.setGroupSummary(false)
|
|
|
|
|
|
|
|
.setGroupAlertBehavior(Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
|
|
|
|
|
|
|
? NotificationCompat.GROUP_ALERT_SUMMARY
|
|
|
|
|
|
|
|
: NotificationCompat.GROUP_ALERT_CHILDREN)
|
|
|
|
|
|
|
|
.setOnlyAlertOnce(true);
|
|
|
|
.setOnlyAlertOnce(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
|
|
|
|
|
|
|
mbuilder
|
|
|
|
|
|
|
|
.setGroup(group)
|
|
|
|
|
|
|
|
.setGroupSummary(false)
|
|
|
|
|
|
|
|
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
|
|
|
|
|
|
int def = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (light) {
|
|
|
|
|
|
|
|
def |= DEFAULT_LIGHTS;
|
|
|
|
|
|
|
|
Log.i("Notify light enabled");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Uri uri = (sound == null ? null : Uri.parse(sound));
|
|
|
|
|
|
|
|
if (uri == null || "file".equals(uri.getScheme()))
|
|
|
|
|
|
|
|
uri = null;
|
|
|
|
|
|
|
|
Log.i("Notify sound=" + uri);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (uri == null)
|
|
|
|
|
|
|
|
def |= DEFAULT_SOUND;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
mbuilder.setSound(uri);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mbuilder.setDefaults(def);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (biometrics)
|
|
|
|
if (biometrics)
|
|
|
|
mbuilder.setContentTitle(context.getResources().getQuantityString(
|
|
|
|
mbuilder.setContentTitle(context.getResources().getQuantityString(
|
|
|
|
R.plurals.title_notification_unseen, 1, 1));
|
|
|
|
R.plurals.title_notification_unseen, 1, 1));
|
|
|
@ -2236,9 +2242,6 @@ class Core {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
|
|
|
|
|
|
|
mbuilder.setSound(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
notifications.add(mbuilder.build());
|
|
|
|
notifications.add(mbuilder.build());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|