568 lines
27 KiB
Java
568 lines
27 KiB
Java
package org.fdroid.fdroid;
|
|
|
|
import android.app.Notification;
|
|
import android.app.PendingIntent;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Point;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build;
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.Spanned;
|
|
import android.text.style.StyleSpan;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.core.app.NotificationChannelCompat;
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.core.app.NotificationManagerCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
|
|
import com.bumptech.glide.Glide;
|
|
import com.bumptech.glide.request.target.CustomTarget;
|
|
import com.bumptech.glide.request.transition.Transition;
|
|
|
|
import org.fdroid.fdroid.data.App;
|
|
import org.fdroid.fdroid.net.DownloaderService;
|
|
import org.fdroid.fdroid.views.AppDetailsActivity;
|
|
import org.fdroid.fdroid.views.main.MainActivity;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
|
|
@SuppressWarnings("LineLength")
|
|
public class NotificationHelper {
|
|
public static final String CHANNEL_SWAPS = "swap-channel";
|
|
public static final String CHANNEL_INSTALLS = "install-channel";
|
|
public static final String CHANNEL_UPDATES = "update-channel";
|
|
|
|
static final String BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED = "org.fdroid.fdroid.installer.notifications.allupdates.cleared";
|
|
static final String BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED = "org.fdroid.fdroid.installer.notifications.allinstalled.cleared";
|
|
static final String BROADCAST_NOTIFICATIONS_UPDATE_CLEARED = "org.fdroid.fdroid.installer.notifications.update.cleared";
|
|
static final String BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED = "org.fdroid.fdroid.installer.notifications.installed.cleared";
|
|
|
|
private static final int NOTIFY_ID_UPDATES = 1;
|
|
private static final int NOTIFY_ID_INSTALLED = 2;
|
|
|
|
private static final int MAX_UPDATES_TO_SHOW = 5;
|
|
private static final int MAX_INSTALLED_TO_SHOW = 10;
|
|
|
|
private static final String GROUP_UPDATES = "updates";
|
|
private static final String GROUP_INSTALLED = "installed";
|
|
|
|
private final Context context;
|
|
private final NotificationManagerCompat notificationManager;
|
|
private final ArrayList<AppUpdateStatusManager.AppUpdateStatus> updates = new ArrayList<>();
|
|
private final ArrayList<AppUpdateStatusManager.AppUpdateStatus> installed = new ArrayList<>();
|
|
|
|
NotificationHelper(Context context) {
|
|
this.context = context;
|
|
notificationManager = NotificationManagerCompat.from(context);
|
|
|
|
final NotificationChannelCompat installChannel = new NotificationChannelCompat.Builder(CHANNEL_INSTALLS,
|
|
NotificationManagerCompat.IMPORTANCE_LOW)
|
|
.setName(context.getString(R.string.notification_channel_installs_title))
|
|
.setDescription(context.getString(R.string.notification_channel_installs_description))
|
|
.build();
|
|
|
|
final NotificationChannelCompat swapChannel = new NotificationChannelCompat.Builder(CHANNEL_SWAPS,
|
|
NotificationManagerCompat.IMPORTANCE_LOW)
|
|
.setName(context.getString(R.string.notification_channel_swaps_title))
|
|
.setDescription(context.getString(R.string.notification_channel_swaps_description))
|
|
.build();
|
|
|
|
final NotificationChannelCompat updateChannel = new NotificationChannelCompat.Builder(CHANNEL_UPDATES,
|
|
NotificationManagerCompat.IMPORTANCE_LOW)
|
|
.setName(context.getString(R.string.notification_channel_updates_title))
|
|
.setDescription(context.getString(R.string.notification_channel_updates_description))
|
|
.build();
|
|
|
|
notificationManager.createNotificationChannelsCompat(Arrays.asList(installChannel, swapChannel,
|
|
updateChannel));
|
|
|
|
IntentFilter filter = new IntentFilter();
|
|
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED);
|
|
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED);
|
|
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED);
|
|
filter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED);
|
|
BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
if (intent == null) {
|
|
return;
|
|
}
|
|
|
|
AppUpdateStatusManager appUpdateStatusManager = AppUpdateStatusManager.getInstance(context);
|
|
AppUpdateStatusManager.AppUpdateStatus entry;
|
|
String url;
|
|
switch (intent.getAction()) {
|
|
case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED:
|
|
notificationManager.cancelAll();
|
|
updateStatusLists();
|
|
createSummaryNotifications();
|
|
for (AppUpdateStatusManager.AppUpdateStatus appUpdateStatus : appUpdateStatusManager.getAll()) {
|
|
createNotification(appUpdateStatus);
|
|
}
|
|
break;
|
|
case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED:
|
|
updateStatusLists();
|
|
createSummaryNotifications();
|
|
url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
|
|
entry = appUpdateStatusManager.get(url);
|
|
if (entry != null) {
|
|
createNotification(entry);
|
|
}
|
|
break;
|
|
case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED:
|
|
url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
|
|
entry = appUpdateStatusManager.get(url);
|
|
updateStatusLists();
|
|
if (entry != null) {
|
|
createNotification(entry);
|
|
}
|
|
if (intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false)) {
|
|
createSummaryNotifications();
|
|
}
|
|
break;
|
|
case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED:
|
|
url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
|
|
notificationManager.cancel(url, NOTIFY_ID_INSTALLED);
|
|
notificationManager.cancel(url, NOTIFY_ID_UPDATES);
|
|
updateStatusLists();
|
|
createSummaryNotifications();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
LocalBroadcastManager.getInstance(context).registerReceiver(receiverAppStatusChanges, filter);
|
|
}
|
|
|
|
private boolean useStackedNotifications() {
|
|
return Build.VERSION.SDK_INT >= 24;
|
|
}
|
|
|
|
/**
|
|
* Populate {@link NotificationHelper#updates} and {@link NotificationHelper#installed} with
|
|
* the relevant status entries from the {@link AppUpdateStatusManager}.
|
|
*/
|
|
private void updateStatusLists() {
|
|
if (!notificationManager.areNotificationsEnabled()) {
|
|
return;
|
|
}
|
|
|
|
updates.clear();
|
|
installed.clear();
|
|
|
|
AppUpdateStatusManager appUpdateStatusManager = AppUpdateStatusManager.getInstance(context);
|
|
for (AppUpdateStatusManager.AppUpdateStatus entry : appUpdateStatusManager.getAll()) {
|
|
if (entry.status == AppUpdateStatusManager.Status.Installed) {
|
|
installed.add(entry);
|
|
} else if (!shouldIgnoreEntry(entry)) {
|
|
updates.add(entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean shouldIgnoreEntry(AppUpdateStatusManager.AppUpdateStatus entry) {
|
|
// Ignore unknown status
|
|
if (entry.status == AppUpdateStatusManager.Status.DownloadInterrupted) {
|
|
return true;
|
|
} else if ((entry.status == AppUpdateStatusManager.Status.Downloading ||
|
|
entry.status == AppUpdateStatusManager.Status.ReadyToInstall ||
|
|
entry.status == AppUpdateStatusManager.Status.InstallError) &&
|
|
AppDetailsActivity.isAppVisible(entry.app.packageName)) {
|
|
// Ignore downloading, readyToInstall and installError if we are showing the details screen for this app
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void createNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
|
|
if (shouldIgnoreEntry(entry)) {
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED);
|
|
return;
|
|
}
|
|
|
|
if (!notificationManager.areNotificationsEnabled() || Preferences.get().hideAllNotifications()) {
|
|
return;
|
|
}
|
|
|
|
Notification notification;
|
|
if (entry.status == AppUpdateStatusManager.Status.Installed) {
|
|
if (useStackedNotifications()) {
|
|
notification = createInstalledNotification(entry);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES);
|
|
notificationManager.notify(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED, notification);
|
|
} else if (installed.size() == 1) {
|
|
notification = createInstalledNotification(entry);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED);
|
|
notificationManager.notify(GROUP_INSTALLED, NOTIFY_ID_INSTALLED, notification);
|
|
}
|
|
} else {
|
|
if (useStackedNotifications()) {
|
|
notification = createUpdateNotification(entry);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED);
|
|
notificationManager.notify(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES, notification);
|
|
} else if (updates.size() == 1) {
|
|
notification = createUpdateNotification(entry);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES);
|
|
notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED);
|
|
notificationManager.notify(GROUP_UPDATES, NOTIFY_ID_UPDATES, notification);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void createSummaryNotifications() {
|
|
if (!notificationManager.areNotificationsEnabled() || Preferences.get().hideAllNotifications()) {
|
|
return;
|
|
}
|
|
|
|
Notification notification;
|
|
if (updates.size() != 1 || useStackedNotifications()) {
|
|
if (updates.isEmpty()) {
|
|
// No updates, remove summary
|
|
notificationManager.cancel(GROUP_UPDATES, NOTIFY_ID_UPDATES);
|
|
} else {
|
|
notification = createUpdateSummaryNotification(updates);
|
|
notificationManager.notify(GROUP_UPDATES, NOTIFY_ID_UPDATES, notification);
|
|
}
|
|
}
|
|
if (installed.size() != 1 || useStackedNotifications()) {
|
|
if (installed.isEmpty()) {
|
|
// No installed, remove summary
|
|
notificationManager.cancel(GROUP_INSTALLED, NOTIFY_ID_INSTALLED);
|
|
} else {
|
|
notification = createInstalledSummaryNotification(installed);
|
|
notificationManager.notify(GROUP_INSTALLED, NOTIFY_ID_INSTALLED, notification);
|
|
}
|
|
}
|
|
}
|
|
|
|
private NotificationCompat.Action getAction(AppUpdateStatusManager.AppUpdateStatus entry) {
|
|
if (entry.intent != null) {
|
|
switch (entry.status) {
|
|
case UpdateAvailable:
|
|
return new NotificationCompat.Action(R.drawable.ic_file_download, context.getString(R.string.notification_action_update), entry.intent);
|
|
|
|
case PendingInstall:
|
|
case Downloading:
|
|
case Installing:
|
|
return new NotificationCompat.Action(R.drawable.ic_cancel, context.getString(R.string.notification_action_cancel), entry.intent);
|
|
|
|
case ReadyToInstall:
|
|
return new NotificationCompat.Action(R.drawable.ic_file_install, context.getString(R.string.notification_action_install), entry.intent);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private String getSingleItemTitleString(App app, AppUpdateStatusManager.Status status) {
|
|
switch (status) {
|
|
case UpdateAvailable:
|
|
return context.getString(R.string.notification_title_single_update_available);
|
|
case PendingInstall:
|
|
case Downloading:
|
|
return app.name;
|
|
case ReadyToInstall:
|
|
return context.getString(app.isInstalled(context) ? R.string.notification_title_single_ready_to_install_update : R.string.notification_title_single_ready_to_install);
|
|
case Installing:
|
|
return app.name;
|
|
case Installed:
|
|
return app.name;
|
|
case InstallError:
|
|
return context.getString(R.string.notification_title_single_install_error);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private String getSingleItemContentString(App app, AppUpdateStatusManager.Status status) {
|
|
switch (status) {
|
|
case UpdateAvailable:
|
|
return app.name;
|
|
case PendingInstall:
|
|
case Downloading:
|
|
return context.getString(app.isInstalled(context) ? R.string.notification_content_single_downloading_update : R.string.notification_content_single_downloading, app.name);
|
|
case ReadyToInstall:
|
|
return app.name;
|
|
case Installing:
|
|
return context.getString(R.string.notification_content_single_installing, app.name);
|
|
case Installed:
|
|
return context.getString(R.string.notification_content_single_installed);
|
|
case InstallError:
|
|
return app.name;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private String getMultiItemContentString(App app, AppUpdateStatusManager.Status status) {
|
|
switch (status) {
|
|
case UpdateAvailable:
|
|
return context.getString(R.string.notification_title_summary_update_available);
|
|
case PendingInstall:
|
|
case Downloading:
|
|
return context.getString(app.isInstalled(context) ? R.string.notification_title_summary_downloading_update : R.string.notification_title_summary_downloading);
|
|
case ReadyToInstall:
|
|
return context.getString(app.isInstalled(context) ? R.string.notification_title_summary_ready_to_install_update : R.string.notification_title_summary_ready_to_install);
|
|
case Installing:
|
|
return context.getString(R.string.notification_title_summary_installing);
|
|
case Installed:
|
|
return context.getString(R.string.notification_title_summary_installed);
|
|
case InstallError:
|
|
return context.getString(R.string.notification_title_summary_install_error);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private Notification createUpdateNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
|
|
App app = entry.app;
|
|
AppUpdateStatusManager.Status status = entry.status;
|
|
|
|
NotificationCompat.Builder builder =
|
|
new NotificationCompat.Builder(context, CHANNEL_UPDATES)
|
|
.setAutoCancel(true)
|
|
.setContentTitle(getSingleItemTitleString(app, status))
|
|
.setContentText(getSingleItemContentString(app, status))
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
|
.setLocalOnly(true)
|
|
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
|
|
.setContentIntent(entry.intent);
|
|
|
|
/* If using stacked notifications, use groups. Note that this would not work prior to Lollipop,
|
|
because of http://stackoverflow.com/a/34953411, but currently not an issue since stacked
|
|
notifications are used only on >= Nougat.
|
|
*/
|
|
if (useStackedNotifications()) {
|
|
builder.setGroup(GROUP_UPDATES);
|
|
}
|
|
|
|
// Handle actions
|
|
//
|
|
NotificationCompat.Action action = getAction(entry);
|
|
if (action != null) {
|
|
builder.addAction(action);
|
|
}
|
|
|
|
// Handle progress bar (for some states)
|
|
//
|
|
if (status == AppUpdateStatusManager.Status.Downloading) {
|
|
if (entry.progressMax == 0) {
|
|
builder.setProgress(100, 0, true);
|
|
} else {
|
|
builder.setProgress(Utils.bytesToKb(entry.progressMax),
|
|
Utils.bytesToKb(entry.progressCurrent), false);
|
|
}
|
|
} else if (status == AppUpdateStatusManager.Status.Installing) {
|
|
builder.setProgress(100, 0, true); // indeterminate bar
|
|
}
|
|
|
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED);
|
|
intentDeleted.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
|
|
intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
|
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
builder.setDeleteIntent(piDeleted);
|
|
loadLargeIconForEntry(entry, builder, NOTIFY_ID_UPDATES, entry.getCanonicalUrl());
|
|
return builder.build();
|
|
}
|
|
|
|
private Notification createUpdateSummaryNotification(ArrayList<AppUpdateStatusManager.AppUpdateStatus> updates) {
|
|
String title = context.getResources().getQuantityString(R.plurals.notification_summary_updates,
|
|
updates.size(), updates.size());
|
|
StringBuilder text = new StringBuilder();
|
|
|
|
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
|
|
inboxStyle.setBigContentTitle(title);
|
|
|
|
for (int i = 0; i < MAX_UPDATES_TO_SHOW && i < updates.size(); i++) {
|
|
AppUpdateStatusManager.AppUpdateStatus entry = updates.get(i);
|
|
App app = entry.app;
|
|
AppUpdateStatusManager.Status status = entry.status;
|
|
|
|
String content = getMultiItemContentString(app, status);
|
|
SpannableStringBuilder sb = new SpannableStringBuilder(app.name);
|
|
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, sb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
|
sb.append(" ");
|
|
sb.append(content);
|
|
inboxStyle.addLine(sb);
|
|
|
|
if (text.length() > 0) {
|
|
text.append(", ");
|
|
}
|
|
text.append(app.name);
|
|
}
|
|
|
|
if (updates.size() > MAX_UPDATES_TO_SHOW) {
|
|
int diff = updates.size() - MAX_UPDATES_TO_SHOW;
|
|
inboxStyle.setSummaryText(context.getResources().getQuantityString(R.plurals.notification_summary_more,
|
|
diff, diff));
|
|
}
|
|
|
|
// Intent to open main app list
|
|
Intent intentObject = new Intent(context, MainActivity.class);
|
|
intentObject.putExtra(MainActivity.EXTRA_VIEW_UPDATES, true);
|
|
PendingIntent piAction = PendingIntent.getActivity(context, 0, intentObject, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
NotificationCompat.Builder builder =
|
|
new NotificationCompat.Builder(context, CHANNEL_UPDATES)
|
|
.setAutoCancel(!useStackedNotifications())
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
|
.setContentTitle(title)
|
|
.setContentText(text)
|
|
.setContentIntent(piAction)
|
|
.setLocalOnly(true)
|
|
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
|
|
.setStyle(inboxStyle);
|
|
|
|
if (useStackedNotifications()) {
|
|
builder.setGroup(GROUP_UPDATES)
|
|
.setGroupSummary(true);
|
|
}
|
|
|
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED);
|
|
intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
|
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
builder.setDeleteIntent(piDeleted);
|
|
return builder.build();
|
|
}
|
|
|
|
private Notification createInstalledNotification(AppUpdateStatusManager.AppUpdateStatus entry) {
|
|
App app = entry.app;
|
|
|
|
NotificationCompat.Builder builder =
|
|
new NotificationCompat.Builder(context, CHANNEL_INSTALLS)
|
|
.setAutoCancel(true)
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
|
.setContentTitle(app.name)
|
|
.setContentText(context.getString(R.string.notification_content_single_installed))
|
|
.setLocalOnly(true)
|
|
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
|
|
.setContentIntent(entry.intent);
|
|
|
|
if (useStackedNotifications()) {
|
|
builder.setGroup(GROUP_INSTALLED);
|
|
}
|
|
|
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED);
|
|
intentDeleted.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
|
|
intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
|
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
builder.setDeleteIntent(piDeleted);
|
|
|
|
loadLargeIconForEntry(entry, builder, NOTIFY_ID_INSTALLED, entry.getCanonicalUrl());
|
|
return builder.build();
|
|
}
|
|
|
|
private Notification createInstalledSummaryNotification(ArrayList<AppUpdateStatusManager.AppUpdateStatus> installed) {
|
|
String title = context.getResources().getQuantityString(R.plurals.notification_summary_installed,
|
|
installed.size(), installed.size());
|
|
StringBuilder text = new StringBuilder();
|
|
|
|
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
|
|
bigTextStyle.setBigContentTitle(title);
|
|
|
|
for (int i = 0; i < MAX_INSTALLED_TO_SHOW && i < installed.size(); i++) {
|
|
AppUpdateStatusManager.AppUpdateStatus entry = installed.get(i);
|
|
App app = entry.app;
|
|
if (text.length() > 0) {
|
|
text.append(", ");
|
|
}
|
|
text.append(app.name);
|
|
}
|
|
bigTextStyle.bigText(text);
|
|
if (installed.size() > MAX_INSTALLED_TO_SHOW) {
|
|
int diff = installed.size() - MAX_INSTALLED_TO_SHOW;
|
|
bigTextStyle.setSummaryText(context.getResources().getQuantityString(R.plurals.notification_summary_more,
|
|
diff, diff));
|
|
}
|
|
|
|
// Intent to open main app list
|
|
Intent intentObject = new Intent(context, MainActivity.class);
|
|
PendingIntent piAction = PendingIntent.getActivity(context, 0, intentObject, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
NotificationCompat.Builder builder =
|
|
new NotificationCompat.Builder(context, CHANNEL_INSTALLS)
|
|
.setAutoCancel(!useStackedNotifications())
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
|
.setContentTitle(title)
|
|
.setContentText(text)
|
|
.setContentIntent(piAction)
|
|
.setLocalOnly(true)
|
|
.setVisibility(NotificationCompat.VISIBILITY_SECRET);
|
|
if (useStackedNotifications()) {
|
|
builder.setGroup(GROUP_INSTALLED)
|
|
.setGroupSummary(true);
|
|
}
|
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED);
|
|
intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
|
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
builder.setDeleteIntent(piDeleted);
|
|
return builder.build();
|
|
}
|
|
|
|
private Point getLargeIconSize() {
|
|
int w = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
|
|
int h = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
|
|
return new Point(w, h);
|
|
}
|
|
|
|
private void loadLargeIconForEntry(AppUpdateStatusManager.AppUpdateStatus entry,
|
|
NotificationCompat.Builder notificationBuilder,
|
|
int notificationId,
|
|
String notificationTag) {
|
|
final Point largeIconSize = getLargeIconSize();
|
|
|
|
if (entry.status == AppUpdateStatusManager.Status.Downloading
|
|
|| entry.status == AppUpdateStatusManager.Status.Installing) {
|
|
Bitmap bitmap = Bitmap.createBitmap(largeIconSize.x, largeIconSize.y, Bitmap.Config.ARGB_8888);
|
|
Canvas canvas = new Canvas(bitmap);
|
|
Drawable downloadIcon = ContextCompat.getDrawable(context, R.drawable.ic_notification_download);
|
|
if (downloadIcon != null) {
|
|
downloadIcon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
downloadIcon.draw(canvas);
|
|
}
|
|
Glide.with(context)
|
|
.asBitmap()
|
|
.load(bitmap)
|
|
.into(new CustomTarget<Bitmap>() {
|
|
@Override
|
|
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
|
// update the loaded large icon, but don't expand
|
|
notificationBuilder.setLargeIcon(resource);
|
|
Notification notification = notificationBuilder.build();
|
|
notificationManager.notify(notificationTag, notificationId, notification);
|
|
}
|
|
|
|
@Override
|
|
public void onLoadCleared(@Nullable Drawable drawable) {
|
|
}
|
|
});
|
|
} else {
|
|
App.loadBitmapWithGlide(context, entry.app.repoId, entry.app.iconFile)
|
|
.into(new CustomTarget<Bitmap>() {
|
|
@Override
|
|
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
|
// update the loaded large icon, but don't expand
|
|
notificationBuilder.setLargeIcon(resource);
|
|
Notification notification = notificationBuilder.build();
|
|
notificationManager.notify(notificationTag, notificationId, notification);
|
|
}
|
|
|
|
@Override
|
|
public void onLoadCleared(@Nullable Drawable drawable) {
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|