diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58f2d7b4e..d380e0aa4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -113,6 +113,13 @@
+
+
+
+
+
+
+ get() = listOf(lastNotification)
+ override val enabledByDefault: Boolean
+ get() = false
+
+ override fun requiredPermissions(sensorId: String): Array {
+ return arrayOf(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE)
+ }
+
+ override fun checkPermission(context: Context, sensorId: String): Boolean {
+ return NotificationManagerCompat
+ .getEnabledListenerPackages(context)
+ .contains(context.packageName)
+ }
+
+ override fun requestSensorUpdate(context: Context) {
+ // Noop
+ }
+
+ override fun onNotificationPosted(sbn: StatusBarNotification) {
+ super.onNotificationPosted(sbn)
+
+ if (!isEnabled(applicationContext, lastNotification.id))
+ return
+
+ val allowPackages = getSetting(
+ applicationContext,
+ lastNotification,
+ "Allow List",
+ "list-apps",
+ ""
+ ).split(", ").filter { it.isNotBlank() }
+
+ if (sbn.packageName == application.packageName ||
+ (allowPackages.isNotEmpty() && sbn.packageName !in allowPackages)) {
+ return
+ }
+
+ val attr = sbn.notification.extras.keySet()
+ .map { it to sbn.notification.extras.get(it) }
+ .toMap()
+ .plus("package" to sbn.packageName)
+
+ // Attempt to use the text of the notification but fallback to package name if all else fails.
+ val state = attr["android.text"] ?: attr["android.title"] ?: sbn.packageName
+
+ onSensorUpdated(
+ applicationContext,
+ lastNotification,
+ state.toString(),
+ "mdi:bell-ring",
+ attr
+ )
+
+ // Need to send update!
+ SensorWorker.start(applicationContext)
+ }
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorDetailFragment.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorDetailFragment.kt
index 4f9901b13..3afce1012 100644
--- a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorDetailFragment.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorDetailFragment.kt
@@ -1,8 +1,11 @@
package io.homeassistant.companion.android.sensors
+import android.Manifest
+import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Handler
+import android.provider.Settings
import android.text.InputType
import androidx.preference.EditTextPreference
import androidx.preference.MultiSelectListPreference
@@ -67,7 +70,12 @@ class SensorDetailFragment(
val isEnabled = newState as Boolean
if (isEnabled && !sensorManager.checkPermission(requireContext(), basicSensor.id)) {
- requestPermissions(sensorManager.requiredPermissions(basicSensor.id), 0)
+ val permissions = sensorManager.requiredPermissions(basicSensor.id)
+ when {
+ permissions.any { perm -> perm == Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE } ->
+ startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
+ else -> requestPermissions(permissions, 0)
+ }
return@setOnPreferenceChangeListener false
}
diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorManager.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorManager.kt
index 8f94747d9..b107256bb 100644
--- a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorManager.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorManager.kt
@@ -8,6 +8,7 @@ import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.database.AppDatabase
import io.homeassistant.companion.android.database.sensor.Attribute
import io.homeassistant.companion.android.database.sensor.Sensor
+import io.homeassistant.companion.android.database.sensor.Setting
interface SensorManager {
@@ -58,6 +59,24 @@ interface SensorManager {
return true
}
+ fun getSetting(
+ context: Context,
+ sensor: BasicSensor,
+ settingName: String,
+ settingType: String,
+ default: String
+ ): String {
+ val sensorDao = AppDatabase.getInstance(context).sensorDao()
+ val setting = sensorDao
+ .getSettings(sensor.id)
+ .firstOrNull { it.name == settingName }
+ ?.value
+ if (setting == null)
+ sensorDao.add(Setting(sensor.id, settingName, default, settingType))
+
+ return setting ?: default
+ }
+
fun onSensorUpdated(
context: Context,
basicSensor: BasicSensor,
diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
index 927196891..aedbcb959 100644
--- a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
@@ -34,6 +34,7 @@ class SensorReceiver : BroadcastReceiver() {
LocationSensorManager(),
NetworkSensorManager(),
NextAlarmManager(),
+ NotificationSensorManager(),
PhoneStateSensorManager(),
PowerSensorManager(),
PressureSensorManager(),
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 86bbadad8..02adc0800 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -40,6 +40,7 @@
Geocoded Location
Interactive
Internal Storage
+ Last Notification
Last Reboot
Single Accurate Location
Background Location
@@ -217,6 +218,7 @@ like to connect to:
Whether or not headphones are plugged into the device
Whether or not the device is in an interactive state
Information about the total and available storage space internally
+ The details of the last notification.
The date and time of the devices last reboot. The setting below will allow you to adjust the deadband in milliseconds, if you still find the value to jump incorrectly. The default value is 60000 (1 minute).
The current level of illuminance
Allow Home Assistant to send a notification to request an accurate location along with the application periodically requesting an accurate location. The Minimum Accuracy setting will allow you to decide how accurate the device location (in meters) has to be in order to send to Home Assistant. The Minimum time between updates (in milliseconds) keeps the device from sending the accurate location too often.
@@ -261,6 +263,7 @@ like to connect to:
Do Not Disturb Sensor
Geolocation Sensors
Headphones
+ Notification Sensors
Last Reboot Sensor
Light Sensor
Location Sensors