Restructure notification channels by intent and importance
Notifications were too intrusive: install-success and export sat on IMPORTANT_HIGH channels and produced heads-up alerts for every app, while genuine download failures were buried in the IMPORTANCE_MIN downloads channel where they were easily missed. Restructure the channels around user intent: - Download progress -> MIN, silent, no badge - Installed apps -> LOW, silent (was HIGH) - Updates available -> DEFAULT, silent - App export -> LOW, silent (was HIGH) - Errors & alerts -> HIGH (new, the only heads-up channel) Failed downloads, installer-status errors and the unarchive auth prompt now route to the high-importance alerts channel so they aren't lost, while successful installs/exports stay quiet. Android ignores importance edits on an already-created channel, so the install/export channels get new IDs and the retired IDs (including the folded-in account channel) are deleted on next launch.
This commit is contained in:
@@ -42,11 +42,22 @@ object Constants {
|
|||||||
const val UPDATE_URL_NIGHTLY =
|
const val UPDATE_URL_NIGHTLY =
|
||||||
"https://auroraoss.com/downloads/AuroraStore/Feeds/nightly_feed.json"
|
"https://auroraoss.com/downloads/AuroraStore/Feeds/nightly_feed.json"
|
||||||
|
|
||||||
const val NOTIFICATION_CHANNEL_EXPORT = "NOTIFICATION_CHANNEL_EXPORT"
|
// Channel IDs carry a version suffix where the importance changed from a previous
|
||||||
const val NOTIFICATION_CHANNEL_INSTALL = "NOTIFICATION_CHANNEL_INSTALL"
|
// release: Android ignores importance edits on an already-created channel, so a new ID
|
||||||
|
// is the only way to roll out a lower importance. Retired IDs are listed in
|
||||||
|
// [LEGACY_NOTIFICATION_CHANNELS] so they can be deleted on next launch.
|
||||||
|
const val NOTIFICATION_CHANNEL_EXPORT = "NOTIFICATION_CHANNEL_EXPORT_V2"
|
||||||
|
const val NOTIFICATION_CHANNEL_INSTALL = "NOTIFICATION_CHANNEL_INSTALLED"
|
||||||
const val NOTIFICATION_CHANNEL_DOWNLOADS = "NOTIFICATION_CHANNEL_DOWNLOADS"
|
const val NOTIFICATION_CHANNEL_DOWNLOADS = "NOTIFICATION_CHANNEL_DOWNLOADS"
|
||||||
const val NOTIFICATION_CHANNEL_UPDATES = "NOTIFICATION_CHANNEL_UPDATES"
|
const val NOTIFICATION_CHANNEL_UPDATES = "NOTIFICATION_CHANNEL_UPDATES"
|
||||||
const val NOTIFICATION_CHANNEL_ACCOUNT = "NOTIFICATION_CHANNEL_ACCOUNT"
|
const val NOTIFICATION_CHANNEL_ALERTS = "NOTIFICATION_CHANNEL_ALERTS"
|
||||||
|
|
||||||
|
// Channels removed or superseded by a higher-versioned ID; deleted on next launch.
|
||||||
|
val LEGACY_NOTIFICATION_CHANNELS = listOf(
|
||||||
|
"NOTIFICATION_CHANNEL_EXPORT",
|
||||||
|
"NOTIFICATION_CHANNEL_INSTALL",
|
||||||
|
"NOTIFICATION_CHANNEL_ACCOUNT"
|
||||||
|
)
|
||||||
|
|
||||||
const val GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
|
const val GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
|
||||||
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
||||||
|
|||||||
@@ -32,38 +32,42 @@ object NotificationUtil {
|
|||||||
|
|
||||||
fun createNotificationChannel(context: Context) {
|
fun createNotificationChannel(context: Context) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val notificationManager = context.getSystemService<NotificationManager>()
|
val notificationManager = context.getSystemService<NotificationManager>()!!
|
||||||
|
|
||||||
|
// Drop channels retired or superseded by a lower-importance replacement, so the
|
||||||
|
// user no longer sees stale entries in system settings.
|
||||||
|
Constants.LEGACY_NOTIFICATION_CHANNELS.forEach {
|
||||||
|
notificationManager.deleteNotificationChannel(it)
|
||||||
|
}
|
||||||
|
|
||||||
val channels = ArrayList<NotificationChannel>()
|
val channels = ArrayList<NotificationChannel>()
|
||||||
channels.add(
|
|
||||||
NotificationChannel(
|
// Quiet, ongoing progress for active downloads. MIN keeps it collapsed and out
|
||||||
Constants.NOTIFICATION_CHANNEL_INSTALL,
|
// of the status bar where possible.
|
||||||
context.getString(R.string.notification_channel_install),
|
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
|
||||||
).apply {
|
|
||||||
setSound(null, null)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
channels.add(
|
|
||||||
NotificationChannel(
|
|
||||||
Constants.NOTIFICATION_CHANNEL_EXPORT,
|
|
||||||
context.getString(R.string.notification_channel_export),
|
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
|
||||||
)
|
|
||||||
)
|
|
||||||
channels.add(
|
|
||||||
NotificationChannel(
|
|
||||||
Constants.NOTIFICATION_CHANNEL_ACCOUNT,
|
|
||||||
context.getString(R.string.notification_channel_account),
|
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
|
||||||
)
|
|
||||||
)
|
|
||||||
channels.add(
|
channels.add(
|
||||||
NotificationChannel(
|
NotificationChannel(
|
||||||
Constants.NOTIFICATION_CHANNEL_DOWNLOADS,
|
Constants.NOTIFICATION_CHANNEL_DOWNLOADS,
|
||||||
context.getString(R.string.notification_channel_downloads),
|
context.getString(R.string.notification_channel_downloads),
|
||||||
NotificationManager.IMPORTANCE_MIN
|
NotificationManager.IMPORTANCE_MIN
|
||||||
)
|
).apply {
|
||||||
|
setSound(null, null)
|
||||||
|
setShowBadge(false)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Silent confirmation that an app finished installing/updating. LOW so it lands
|
||||||
|
// in the shade without buzzing for every app during a bulk update.
|
||||||
|
channels.add(
|
||||||
|
NotificationChannel(
|
||||||
|
Constants.NOTIFICATION_CHANNEL_INSTALL,
|
||||||
|
context.getString(R.string.notification_channel_install),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
).apply {
|
||||||
|
setSound(null, null)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// New updates are available to install. DEFAULT but silent.
|
||||||
channels.add(
|
channels.add(
|
||||||
NotificationChannel(
|
NotificationChannel(
|
||||||
Constants.NOTIFICATION_CHANNEL_UPDATES,
|
Constants.NOTIFICATION_CHANNEL_UPDATES,
|
||||||
@@ -73,7 +77,29 @@ object NotificationUtil {
|
|||||||
setSound(null, null)
|
setSound(null, null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
notificationManager!!.createNotificationChannels(channels)
|
|
||||||
|
// Background app export. LOW since it's user-initiated and non-urgent.
|
||||||
|
channels.add(
|
||||||
|
NotificationChannel(
|
||||||
|
Constants.NOTIFICATION_CHANNEL_EXPORT,
|
||||||
|
context.getString(R.string.notification_channel_export),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
).apply {
|
||||||
|
setSound(null, null)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Things the user genuinely needs to act on: failed downloads/installs, pending
|
||||||
|
// user action and authentication prompts. HIGH so these aren't missed.
|
||||||
|
channels.add(
|
||||||
|
NotificationChannel(
|
||||||
|
Constants.NOTIFICATION_CHANNEL_ALERTS,
|
||||||
|
context.getString(R.string.notification_channel_alerts),
|
||||||
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
notificationManager.createNotificationChannels(channels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +117,14 @@ object NotificationUtil {
|
|||||||
largeIcon: Bitmap? = null,
|
largeIcon: Bitmap? = null,
|
||||||
message: String? = null
|
message: String? = null
|
||||||
): Notification {
|
): Notification {
|
||||||
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_DOWNLOADS)
|
// Terminal failures go to the high-importance alerts channel so they aren't lost in
|
||||||
|
// the silent downloads channel; everything else stays quiet.
|
||||||
|
val channelId = if (download.status == DownloadStatus.FAILED) {
|
||||||
|
Constants.NOTIFICATION_CHANNEL_ALERTS
|
||||||
|
} else {
|
||||||
|
Constants.NOTIFICATION_CHANNEL_DOWNLOADS
|
||||||
|
}
|
||||||
|
val builder = NotificationCompat.Builder(context, channelId)
|
||||||
builder.setSmallIcon(R.drawable.ic_notification_outlined)
|
builder.setSmallIcon(R.drawable.ic_notification_outlined)
|
||||||
builder.setContentTitle(download.displayName)
|
builder.setContentTitle(download.displayName)
|
||||||
builder.setContentIntent(getContentIntentForDetails(context, download.packageName))
|
builder.setContentIntent(getContentIntentForDetails(context, download.packageName))
|
||||||
@@ -197,11 +230,12 @@ object NotificationUtil {
|
|||||||
packageName: String,
|
packageName: String,
|
||||||
displayName: String,
|
displayName: String,
|
||||||
content: String?
|
content: String?
|
||||||
): Notification = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_INSTALL)
|
): Notification = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERTS)
|
||||||
.setSmallIcon(R.drawable.ic_install)
|
.setSmallIcon(R.drawable.ic_install)
|
||||||
.setContentTitle(displayName)
|
.setContentTitle(displayName)
|
||||||
.setContentText(content)
|
.setContentText(content)
|
||||||
.setContentIntent(getContentIntentForDetails(context, packageName))
|
.setContentIntent(getContentIntentForDetails(context, packageName))
|
||||||
|
.setCategory(Notification.CATEGORY_ERROR)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun getUpdateNotification(context: Context): Notification =
|
fun getUpdateNotification(context: Context): Notification =
|
||||||
@@ -289,7 +323,7 @@ object NotificationUtil {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun getUnarchiveAuthNotification(context: Context, packageName: String): Notification =
|
fun getUnarchiveAuthNotification(context: Context, packageName: String): Notification =
|
||||||
NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ACCOUNT)
|
NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERTS)
|
||||||
.setSmallIcon(R.drawable.ic_account)
|
.setSmallIcon(R.drawable.ic_account)
|
||||||
.setContentTitle(context.getString(R.string.authentication_required_title))
|
.setContentTitle(context.getString(R.string.authentication_required_title))
|
||||||
.setContentText(context.getString(R.string.authentication_required_unarchive))
|
.setContentText(context.getString(R.string.authentication_required_unarchive))
|
||||||
|
|||||||
@@ -211,7 +211,7 @@
|
|||||||
<string name="device_miui_extra">"Optionally you can choose Native installer, but then you can not install bundled (split) APKs, so choice is yours."</string>
|
<string name="device_miui_extra">"Optionally you can choose Native installer, but then you can not install bundled (split) APKs, so choice is yours."</string>
|
||||||
<string name="dialog_title_self_update">"New update available"</string>
|
<string name="dialog_title_self_update">"New update available"</string>
|
||||||
<string name="dialog_desc_native_split">"You can not install bundled (split) apps via Native Installer. Change your installer to Session, Services or Root."</string>
|
<string name="dialog_desc_native_split">"You can not install bundled (split) apps via Native Installer. Change your installer to Session, Services or Root."</string>
|
||||||
<string name="notification_channel_account">Account-related notification</string>
|
<string name="notification_channel_alerts">Errors & alerts</string>
|
||||||
<string name="notification_channel_export">App export notification</string>
|
<string name="notification_channel_export">App export notification</string>
|
||||||
<string name="notification_channel_install">Install notification</string>
|
<string name="notification_channel_install">Install notification</string>
|
||||||
<string name="notification_channel_downloads">Downloads notification</string>
|
<string name="notification_channel_downloads">Downloads notification</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user