Skip to content

Commit

Permalink
properly handle notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
newhinton committed Aug 31, 2024
1 parent 08d1766 commit 0ddd83c
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 33 deletions.
1 change: 1 addition & 0 deletions app/src/main/java/de/felixnuesse/timedsilence/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class Constants {
const val REASON_KEYWORD = 3
const val REASON_MANUALLY_SET = 4
const val REASON_BLUETOOTH_CONNECTED = 5
const val REASON_NOTIFICATION_VISIBLE = 6
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package de.felixnuesse.timedsilence.handler.volume

import de.felixnuesse.timedsilence.Constants.Companion.REASON_BLUETOOTH_CONNECTED
import de.felixnuesse.timedsilence.Constants.Companion.REASON_CALENDAR
import de.felixnuesse.timedsilence.Constants.Companion.REASON_KEYWORD
import de.felixnuesse.timedsilence.Constants.Companion.REASON_MANUALLY_SET
import de.felixnuesse.timedsilence.Constants.Companion.REASON_NOTIFICATION_VISIBLE
import de.felixnuesse.timedsilence.Constants.Companion.REASON_TIME
import de.felixnuesse.timedsilence.Constants.Companion.REASON_UNDEFINED
import de.felixnuesse.timedsilence.Constants.Companion.REASON_WIFI
Expand Down Expand Up @@ -44,6 +46,7 @@ class VolumeState(var state: Int) {
this.reasonDescription = reasonDescription
}

// in milliseconds
var startTime: Long = 0
var endTime: Long = startTime

Expand All @@ -69,6 +72,8 @@ class VolumeState(var state: Int) {
REASON_UNDEFINED -> s = "Default Volume."
REASON_WIFI -> s = "Volume changed because of wifi: $reasonDescription"
REASON_MANUALLY_SET -> s = "Volume was set manually: $reasonDescription"
REASON_BLUETOOTH_CONNECTED -> s = "Volume was set because bluetooth was connected: $reasonDescription"
REASON_NOTIFICATION_VISIBLE -> s = "Notification Visible: $reasonDescription"
}
return s
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
package de.felixnuesse.timedsilence.receiver


import android.os.Build
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import de.felixnuesse.timedsilence.Constants
import androidx.annotation.RequiresApi
import de.felixnuesse.timedsilence.extensions.TAG
import de.felixnuesse.timedsilence.handler.PreferencesManager
import de.felixnuesse.timedsilence.handler.volume.VolumeHandler
import de.felixnuesse.timedsilence.handler.volume.VolumeState
import de.felixnuesse.timedsilence.model.database.DatabaseHandler
import de.felixnuesse.timedsilence.volumestate.StateGenerator


class NotificationListener : NotificationListenerService() {

private val TAG: String = this.javaClass.simpleName
companion object {
private var service: NotificationListener? = null
fun getService(): NotificationListener? {
return service
}
}

override fun onNotificationPosted(notification: StatusBarNotification) {
handleNotification(false, notification)
var allNotifications = arrayListOf<StatusBarNotification>()

override fun onCreate() {
super.onCreate()
service = this
}

override fun onNotificationRemoved(notification: StatusBarNotification) {
handleNotification(true, notification)
fun getAllActiveNotifications(): ArrayList<StatusBarNotification> {
return allNotifications
}

fun handleNotification(isRemove: Boolean, notification: StatusBarNotification) {
val proceed = PreferencesManager(this).shouldSearchInNotifications()
if(!proceed) {
override fun onNotificationPosted(notification: StatusBarNotification) {
if(notification.packageName == this.baseContext.packageName) {
return
}
allNotifications.clear()
allNotifications.addAll(activeNotifications)
handleNotification()
}

if(isRemove) {
Log.e(TAG(), "NotificationListener: Removed notification, check!")
VolumeHandler(this, "NotificationListener").setVolumeStateAndApply(StateGenerator(this).stateAt(System.currentTimeMillis()))
override fun onNotificationRemoved(notification: StatusBarNotification) {
if(notification.packageName == this.baseContext.packageName) {
return
}
allNotifications.clear()
allNotifications.addAll(activeNotifications)
handleNotification()
}

Log.e(TAG(), "NotificationListener: Posted notification, check!")

val toSearch = notification.notification.extras.toString()+notification.notification.toString()+notification.toString()

val db = DatabaseHandler(this)
db.getKeywords().forEach {
if (toSearch.lowercase().contains(it.keyword.lowercase())) {
val state = VolumeState(it.volume)
state.setReason(Constants.REASON_MANUALLY_SET, "Keyword ${it.keyword} was found in notification")
VolumeHandler(this, "NotificationListener").setVolumeStateAndApply(state)
return
}
private fun handleNotification() {
val proceed = PreferencesManager(this).shouldSearchInNotifications()
if(!proceed) {
return
}
}

Log.e(TAG(), "NotificationListener: Posted or removed notification, check!")
VolumeHandler(this, "NotificationListener").setVolumeStateAndApply(StateGenerator(this).stateAt(System.currentTimeMillis()))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package de.felixnuesse.timedsilence.volumestate


import android.app.NotificationManager
import android.content.Context
import android.service.notification.StatusBarNotification
import android.util.Log
import de.felixnuesse.timedsilence.Constants
import de.felixnuesse.timedsilence.extensions.TAG
import de.felixnuesse.timedsilence.handler.PreferencesManager
import de.felixnuesse.timedsilence.handler.volume.VolumeState
import de.felixnuesse.timedsilence.handler.volume.VolumeState.Companion.TIME_SETTING_UNSET
import de.felixnuesse.timedsilence.handler.volume.VolumeState.Companion.isFirstLouder
import de.felixnuesse.timedsilence.model.database.DatabaseHandler
import de.felixnuesse.timedsilence.receiver.NotificationListener


open class Notifications(private var mContext: Context): DeterministicCalculationInterface() {

private val mPrefs = PreferencesManager(mContext)
private val mDB = DatabaseHandler(mContext)

override fun stateAt(timeInMs: Long): ArrayList<VolumeState> {
return ArrayList()
}

override fun states(): ArrayList<VolumeState> {
val list = ArrayList<VolumeState>()

if(mPrefs.shouldSearchInNotifications()) {
var currentVolumeState = VolumeState(TIME_SETTING_UNSET)
NotificationListener.getService()?.getAllActiveNotifications()?.forEach {
val checkedState = handleNotification(it)?: VolumeState(TIME_SETTING_UNSET)
if (isFirstLouder(checkedState, currentVolumeState)) {
currentVolumeState = checkedState
}
}
if(currentVolumeState.state != TIME_SETTING_UNSET){
list.add(currentVolumeState)
}
}

Log.e(TAG(), "Size: ${list.size}")
return list
}

private fun handleNotification(notification: StatusBarNotification): VolumeState? {
Log.e(TAG(), "Size: ${notification.notification}")
val toSearch = notification.notification.extras.toString()+notification.notification.toString()+notification.toString()

mDB.getKeywords().forEach {
if (toSearch.lowercase().contains(it.keyword.lowercase())) {
val state = VolumeState(it.volume)
state.startTime = System.currentTimeMillis()
state.endTime = state.startTime + 60*1000 // add a minute
state.setReason(Constants.REASON_NOTIFICATION_VISIBLE, "Keyword: ${it.keyword}")
return state
}
}
return null
}

override fun isEnabled(): Boolean {
return mPrefs.shouldSearchInNotifications()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class StateGenerator(private var mContext: Context) {
private var mEvents = Events(mContext)
private var mKeywords = Keywords(mContext)
private var mSchedules = Schedule(mContext)
private var mNotifications = Notifications(mContext)

init {
LogHandler.writeLog(mContext, TAG(), "instantiate","VolumeCalculator was now instantiated")
Expand All @@ -50,6 +51,7 @@ class StateGenerator(private var mContext: Context) {
stateList.addAll(mEvents.states())
stateList.addAll(mKeywords.states())
stateList.addAll(mSchedules.states())
stateList.addAll(mNotifications.states())

Collections.sort(stateList, VolumeStateStartComparator())

Expand All @@ -64,13 +66,13 @@ class StateGenerator(private var mContext: Context) {

// Todo: check if the performance can be improved
timeList.forEach {
var deleteList = ArrayList<VolumeState>()
var addList = ArrayList<VolumeState>()
val deleteList = ArrayList<VolumeState>()
val addList = ArrayList<VolumeState>()

for(state in stateList) {
if(state.startTime < it && it < state.endTime) {
var a = state.copy()
var b = state.copy()
val a = state.copy()
val b = state.copy()

a.endTime = it
b.startTime = it
Expand All @@ -95,7 +97,7 @@ class StateGenerator(private var mContext: Context) {
}
}

var linearList = ArrayList<VolumeState>()
val linearList = ArrayList<VolumeState>()
map.forEach { (_, value) ->
if(value.size > 1) {
Collections.sort(value, VolumeStateStateComparator())
Expand Down

0 comments on commit 0ddd83c

Please sign in to comment.