NotificationUtil: Move notification related logic into separate Util class

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-10-25 13:38:06 +05:30
parent ca881413eb
commit dca5863ba8
3 changed files with 273 additions and 242 deletions

View File

@@ -21,16 +21,13 @@
package com.aurora.store
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
import androidx.core.content.ContextCompat
import com.aurora.Constants
import com.aurora.extensions.isPAndAbove
import com.aurora.store.data.downloader.DownloadManager
import com.aurora.store.data.receiver.PackageManagerReceiver
import com.aurora.store.data.service.NotificationService
import com.aurora.store.util.CommonUtil
import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PackageUtil
import com.tonyodev.fetch2.Fetch
import org.lsposed.hiddenapibypass.HiddenApiBypass
@@ -53,8 +50,7 @@ class AuroraApplication : Application() {
}
//Create Notification Channels : General & Alert
createNotificationChannel()
NotificationUtil.createNotificationChannel(this)
NotificationService.startService(this)
fetch = DownloadManager.with(this).fetch
@@ -70,43 +66,4 @@ class AuroraApplication : Application() {
CommonUtil.cleanupInstallationSessions(applicationContext)
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val channels = ArrayList<NotificationChannel>()
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_ALERT,
getString(R.string.notification_channel_alert),
NotificationManager.IMPORTANCE_HIGH
).apply {
setSound(null, null)
}
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_GENERAL,
getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_MIN
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_UPDATER_SERVICE,
getString(R.string.notification_channel_updater_service),
NotificationManager.IMPORTANCE_MIN
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_UPDATES,
getString(R.string.notification_channel_updates),
NotificationManager.IMPORTANCE_DEFAULT
).apply {
setSound(null, null)
}
)
notificationManager.createNotificationChannels(channels)
}
}
}

View File

@@ -20,36 +20,21 @@
package com.aurora.store.data.service
import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.IBinder
import android.util.ArrayMap
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.navigation.NavDeepLinkBuilder
import com.aurora.Constants
import com.aurora.extensions.getStyledAttributeColor
import com.aurora.extensions.isMAndAbove
import com.aurora.gplayapi.data.models.App
import com.aurora.store.MainActivity
import com.aurora.store.R
import com.aurora.store.data.downloader.DownloadManager
import com.aurora.store.data.downloader.RequestGroupIdBuilder
import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.installer.AppInstaller
import com.aurora.store.data.receiver.DownloadCancelReceiver
import com.aurora.store.data.receiver.DownloadPauseReceiver
import com.aurora.store.data.receiver.DownloadResumeReceiver
import com.aurora.store.data.receiver.InstallReceiver
import com.aurora.store.util.CommonUtil
import com.aurora.store.util.Log
import com.aurora.store.util.NotificationUtil
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.tonyodev.fetch2.AbstractFetchGroupListener
@@ -58,9 +43,9 @@ import com.tonyodev.fetch2.Error
import com.tonyodev.fetch2.Fetch
import com.tonyodev.fetch2.FetchGroup
import com.tonyodev.fetch2.Status
import java.lang.reflect.Modifier
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import java.lang.reflect.Modifier
class NotificationService : Service() {
@@ -149,10 +134,8 @@ class NotificationService : Service() {
}
private fun showNotification(groupId: Int, download: Download, fetchGroup: FetchGroup) {
val status = download.status
//Ignore notifications for completion of sub-parts of a bundled apk
if (status == Status.COMPLETED && fetchGroup.groupDownloadProgress < 100)
if (download.status == Status.COMPLETED && fetchGroup.groupDownloadProgress < 100)
return
//synchronized(appMap) {
@@ -169,187 +152,20 @@ class NotificationService : Service() {
if (app == null)
return
if (status == Status.DELETED) {
if (download.status == Status.DELETED) {
notificationManager.cancel(app.id)
return
}
val builder = NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNEL_GENERAL)
builder.setContentTitle(app.displayName)
builder.setSmallIcon(R.drawable.ic_notification_outlined)
builder.color = ContextCompat.getColor(this, R.color.colorAccent)
builder.setWhen(download.created)
builder.setContentIntent(getContentIntentForDownloads())
when (status) {
Status.PAUSED -> {
builder.setSmallIcon(R.drawable.ic_download_pause)
builder.setContentText(getString(R.string.download_paused))
}
Status.CANCELLED -> {
builder.setSmallIcon(R.drawable.ic_download_cancel)
builder.setContentText(getString(R.string.download_canceled))
builder.color = Color.RED
}
Status.FAILED ->
{
builder.setSmallIcon(R.drawable.ic_download_fail)
builder.setContentText(getString(R.string.download_failed))
builder.color = Color.RED
}
Status.COMPLETED -> if (fetchGroup.groupDownloadProgress == 100) {
builder.setSmallIcon(android.R.drawable.stat_sys_download_done)
builder.setContentText(getString(R.string.download_completed))
}
else -> {
builder.setSmallIcon(android.R.drawable.stat_sys_download)
builder.setContentText(getString(R.string.download_metadata))
}
}
val progress = fetchGroup.groupDownloadProgress
val progressBigText = NotificationCompat.BigTextStyle()
when (status) {
Status.QUEUED -> {
builder.setProgress(100, 0, true)
progressBigText.bigText(getString(R.string.download_queued))
builder.setStyle(progressBigText)
}
Status.DOWNLOADING -> {
val speedString: String =
CommonUtil.humanReadableByteSpeed(download.downloadedBytesPerSecond, true)
progressBigText.bigText(
getString(
R.string.download_progress,
fetchGroup.completedDownloads.size + 1,
fetchGroup.downloads.size,
speedString
)
)
builder.setStyle(progressBigText)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_pause,
getString(R.string.action_pause),
getPauseIntent(groupId)
).build()
)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_cancel,
getString(R.string.action_cancel),
getCancelIntent(groupId)
).build()
)
if (progress < 0) builder.setProgress(
100,
0,
true
) else builder.setProgress(100, progress, false)
}
Status.PAUSED -> {
progressBigText.bigText(
getString(
R.string.download_paused,
fetchGroup.completedDownloads.size,
fetchGroup.downloads.size
)
)
builder.setStyle(progressBigText)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_pause,
getString(R.string.action_resume),
getResumeIntent(groupId)
).build()
)
}
Status.COMPLETED -> if (fetchGroup.groupDownloadProgress == 100) {
builder.setAutoCancel(true)
builder.setContentIntent(getContentIntentForDetails(app))
builder.setStyle(progressBigText)
}
else -> {
}
}
when (status) {
Status.DOWNLOADING -> builder.setCategory(Notification.CATEGORY_PROGRESS)
Status.FAILED, Status.CANCELLED -> builder.setCategory(Notification.CATEGORY_ERROR)
else -> builder.setCategory(Notification.CATEGORY_STATUS)
}
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
notificationManager.notify(
app.packageName,
app.id,
builder.build()
NotificationUtil.getDownloadNotification(this, app, groupId, download, fetchGroup)
)
}
}
private fun getPauseIntent(groupId: Int): PendingIntent {
val intent = Intent(this, DownloadPauseReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(this, groupId, intent, flags)
}
private fun getResumeIntent(groupId: Int): PendingIntent {
val intent = Intent(this, DownloadResumeReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(this, groupId, intent, flags)
}
private fun getCancelIntent(groupId: Int): PendingIntent {
val intent = Intent(this, DownloadCancelReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(this, groupId, intent, flags)
}
private fun getContentIntentForDetails(app: App?): PendingIntent {
return NavDeepLinkBuilder(this)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.appDetailsFragment)
.setComponentName(MainActivity::class.java)
.setArguments(bundleOf("packageName" to app!!.packageName))
.createPendingIntent()
}
private fun getContentIntentForDownloads(): PendingIntent {
return NavDeepLinkBuilder(this)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.downloadFragment)
.setComponentName(MainActivity::class.java)
.createPendingIntent()
}
private fun getInstallIntent(packageName: String): PendingIntent {
val intent = Intent(this, InstallReceiver::class.java)
intent.putExtra(Constants.STRING_EXTRA, packageName)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(
this,
packageName.hashCode(),
intent,
flags
)
}
@Subscribe()
fun onEventMainThread(event: Any) {
when (event) {
@@ -398,18 +214,11 @@ class NotificationService : Service() {
}
private fun notifyInstallationStatus(app: App, status: String?) {
val builder = NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNEL_ALERT)
builder.color = getStyledAttributeColor(R.color.colorAccent)
builder.setSmallIcon(R.drawable.ic_install)
builder.setContentTitle(app.displayName)
builder.setContentText(status)
builder.setSubText(app.packageName)
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
notificationManager.notify(
app.packageName,
app.id,
builder.build()
NotificationUtil.getInstallNotification(this, app, status)
)
}
}

View File

@@ -0,0 +1,265 @@
package com.aurora.store.util
import android.app.Application
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.navigation.NavDeepLinkBuilder
import com.aurora.Constants
import com.aurora.extensions.getStyledAttributeColor
import com.aurora.extensions.isMAndAbove
import com.aurora.gplayapi.data.models.App
import com.aurora.store.MainActivity
import com.aurora.store.R
import com.aurora.store.data.receiver.DownloadCancelReceiver
import com.aurora.store.data.receiver.DownloadPauseReceiver
import com.aurora.store.data.receiver.DownloadResumeReceiver
import com.aurora.store.data.receiver.InstallReceiver
import com.tonyodev.fetch2.Download
import com.tonyodev.fetch2.FetchGroup
import com.tonyodev.fetch2.Status
object NotificationUtil {
fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager =
context.getSystemService(Application.NOTIFICATION_SERVICE) as NotificationManager
val channels = ArrayList<NotificationChannel>()
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_ALERT,
context.getString(R.string.notification_channel_alert),
NotificationManager.IMPORTANCE_HIGH
).apply {
setSound(null, null)
}
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_GENERAL,
context.getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_MIN
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_UPDATER_SERVICE,
context.getString(R.string.notification_channel_updater_service),
NotificationManager.IMPORTANCE_MIN
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_UPDATES,
context.getString(R.string.notification_channel_updates),
NotificationManager.IMPORTANCE_DEFAULT
).apply {
setSound(null, null)
}
)
notificationManager.createNotificationChannels(channels)
}
}
fun getDownloadNotification(
context: Context,
app: App,
groupId: Int,
download: Download,
fetchGroup: FetchGroup
): Notification {
val status = download.status
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_GENERAL)
builder.setContentTitle(app.displayName)
builder.setSmallIcon(R.drawable.ic_notification_outlined)
builder.color = ContextCompat.getColor(context, R.color.colorAccent)
builder.setWhen(download.created)
builder.setContentIntent(getContentIntentForDownloads(context))
when (status) {
Status.PAUSED -> {
builder.setSmallIcon(R.drawable.ic_download_pause)
builder.setContentText(context.getString(R.string.download_paused))
}
Status.CANCELLED -> {
builder.setSmallIcon(R.drawable.ic_download_cancel)
builder.setContentText(context.getString(R.string.download_canceled))
builder.color = Color.RED
}
Status.FAILED -> {
builder.setSmallIcon(R.drawable.ic_download_fail)
builder.setContentText(context.getString(R.string.download_failed))
builder.color = Color.RED
}
Status.COMPLETED -> if (fetchGroup.groupDownloadProgress == 100) {
builder.setSmallIcon(android.R.drawable.stat_sys_download_done)
builder.setContentText(context.getString(R.string.download_completed))
}
else -> {
builder.setSmallIcon(android.R.drawable.stat_sys_download)
builder.setContentText(context.getString(R.string.download_metadata))
}
}
val progress = fetchGroup.groupDownloadProgress
val progressBigText = NotificationCompat.BigTextStyle()
when (status) {
Status.QUEUED -> {
builder.setProgress(100, 0, true)
progressBigText.bigText(context.getString(R.string.download_queued))
builder.setStyle(progressBigText)
}
Status.DOWNLOADING -> {
val speedString: String =
CommonUtil.humanReadableByteSpeed(download.downloadedBytesPerSecond, true)
progressBigText.bigText(
context.getString(
R.string.download_progress,
fetchGroup.completedDownloads.size + 1,
fetchGroup.downloads.size,
speedString
)
)
builder.setStyle(progressBigText)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_pause,
context.getString(R.string.action_pause),
getPauseIntent(context, groupId)
).build()
)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_cancel,
context.getString(R.string.action_cancel),
getCancelIntent(context, groupId)
).build()
)
if (progress < 0) builder.setProgress(
100,
0,
true
) else builder.setProgress(100, progress, false)
}
Status.PAUSED -> {
progressBigText.bigText(
context.getString(
R.string.download_paused,
fetchGroup.completedDownloads.size,
fetchGroup.downloads.size
)
)
builder.setStyle(progressBigText)
builder.addAction(
NotificationCompat.Action.Builder(
R.drawable.ic_download_pause,
context.getString(R.string.action_resume),
getResumeIntent(context, groupId)
).build()
)
}
Status.COMPLETED -> if (fetchGroup.groupDownloadProgress == 100) {
builder.setAutoCancel(true)
builder.setContentIntent(getContentIntentForDetails(context, app))
builder.setStyle(progressBigText)
}
else -> {
}
}
when (status) {
Status.DOWNLOADING -> builder.setCategory(Notification.CATEGORY_PROGRESS)
Status.FAILED, Status.CANCELLED -> builder.setCategory(Notification.CATEGORY_ERROR)
else -> builder.setCategory(Notification.CATEGORY_STATUS)
}
return builder.build()
}
fun getInstallNotification(context: Context, app: App, content: String?): Notification {
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT)
builder.color = context.getStyledAttributeColor(R.color.colorAccent)
builder.setSmallIcon(R.drawable.ic_install)
builder.setContentTitle(app.displayName)
builder.setContentText(content)
builder.setSubText(app.packageName)
return builder.build()
}
private fun getPauseIntent(context: Context, groupId: Int): PendingIntent {
val intent = Intent(context, DownloadPauseReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(context, groupId, intent, flags)
}
private fun getResumeIntent(context: Context, groupId: Int): PendingIntent {
val intent = Intent(context, DownloadResumeReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(context, groupId, intent, flags)
}
private fun getCancelIntent(context: Context, groupId: Int): PendingIntent {
val intent = Intent(context, DownloadCancelReceiver::class.java)
intent.putExtra(Constants.FETCH_GROUP_ID, groupId)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(context, groupId, intent, flags)
}
private fun getContentIntentForDetails(context: Context, app: App?): PendingIntent {
return NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.appDetailsFragment)
.setComponentName(MainActivity::class.java)
.setArguments(bundleOf("packageName" to app!!.packageName))
.createPendingIntent()
}
private fun getContentIntentForDownloads(context: Context): PendingIntent {
return NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.downloadFragment)
.setComponentName(MainActivity::class.java)
.createPendingIntent()
}
private fun getInstallIntent(context: Context, packageName: String): PendingIntent {
val intent = Intent(context, InstallReceiver::class.java)
intent.putExtra(Constants.STRING_EXTRA, packageName)
val flags = if (isMAndAbove())
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
else PendingIntent.FLAG_CANCEL_CURRENT
return PendingIntent.getBroadcast(
context,
packageName.hashCode(),
intent,
flags
)
}
}