NotificationService.kt raw

   1  package io.github.domi04151309.alwayson.services
   2  
   3  import android.app.Notification
   4  import android.content.Intent
   5  import android.graphics.drawable.Icon
   6  import android.os.Handler
   7  import android.os.Looper
   8  import android.service.notification.NotificationListenerService
   9  import android.service.notification.StatusBarNotification
  10  import android.util.Log
  11  import androidx.preference.PreferenceManager
  12  import io.github.domi04151309.alwayson.actions.alwayson.AlwaysOn
  13  import io.github.domi04151309.alwayson.helpers.ColorHelper
  14  import io.github.domi04151309.alwayson.helpers.Global
  15  import io.github.domi04151309.alwayson.helpers.JSON
  16  import io.github.domi04151309.alwayson.helpers.Rules
  17  import io.github.domi04151309.alwayson.receivers.CombinedServiceReceiver
  18  import org.json.JSONArray
  19  
  20  class NotificationService : NotificationListenerService() {
  21      private var sentRecently: Boolean = false
  22      private var previousCount: Int = -1
  23  
  24      interface OnNotificationsChangedListener {
  25          fun onNotificationsChanged()
  26      }
  27  
  28      override fun onCreate() {
  29          super.onCreate()
  30          updateValues()
  31      }
  32  
  33      override fun onNotificationPosted(notification: StatusBarNotification) {
  34          updateValues()
  35  
  36          val rules = Rules(this)
  37          @Suppress("ComplexCondition")
  38          if (
  39              isValidNotification(notification) &&
  40              !CombinedServiceReceiver.isScreenOn &&
  41              !CombinedServiceReceiver.isAlwaysOnRunning &&
  42              Rules.isAmbientMode(this) &&
  43              rules.canShow(this) &&
  44              count >= 1
  45          ) {
  46              startActivity(
  47                  Intent(
  48                      this,
  49                      AlwaysOn::class.java,
  50                  ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
  51              )
  52          }
  53      }
  54  
  55      override fun onNotificationRemoved(notification: StatusBarNotification) {
  56          updateValues()
  57  
  58          if (
  59              CombinedServiceReceiver.isAlwaysOnRunning &&
  60              Rules.isAmbientMode(this) &&
  61              count < 1
  62          ) {
  63              AlwaysOn.finish()
  64          }
  65      }
  66  
  67      private fun updateValues() {
  68          if (sentRecently) return
  69  
  70          sentRecently = true
  71          try {
  72              val apps = ArrayList<String>(detailed.size)
  73              detailed = activeNotifications
  74              icons = ArrayList(detailed.size)
  75              count = 0
  76              for (notification in detailed) {
  77                  if (!isValidNotification(notification)) continue
  78                  if (
  79                      notification.notification.flags and Notification.FLAG_GROUP_SUMMARY == 0
  80                  ) {
  81                      count++
  82                  }
  83                  if (!apps.contains(notification.packageName)) {
  84                      apps += notification.packageName
  85                      icons.add(
  86                          Pair(
  87                              notification.notification.smallIcon,
  88                              ColorHelper.boostColor(notification.notification.color),
  89                          ),
  90                      )
  91                  }
  92              }
  93          } catch (exception: SecurityException) {
  94              Log.e(Global.LOG_TAG, exception.toString())
  95              count = 0
  96              icons = arrayListOf()
  97          }
  98          if (previousCount != count) {
  99              previousCount = count
 100              listeners.forEach { it.onNotificationsChanged() }
 101          }
 102          Handler(Looper.getMainLooper()).postDelayed({ sentRecently = false }, MINIMUM_UPDATE_DELAY)
 103      }
 104  
 105      private fun isValidNotification(notification: StatusBarNotification): Boolean =
 106          !notification.isOngoing &&
 107              !JSON.contains(
 108                  JSONArray(
 109                      PreferenceManager.getDefaultSharedPreferences(this)
 110                          .getString("blocked_notifications", "[]"),
 111                  ),
 112                  notification.packageName,
 113              )
 114  
 115      companion object {
 116          const val MINIMUM_UPDATE_DELAY: Long = 1000
 117          internal var count: Int = 0
 118              private set
 119          internal var icons: ArrayList<Pair<Icon, Int>> = arrayListOf()
 120              private set
 121          internal var detailed: Array<StatusBarNotification> = arrayOf()
 122              private set
 123  
 124          @JvmField
 125          internal val listeners: ArrayList<OnNotificationsChangedListener> = arrayListOf()
 126      }
 127  }
 128