mirror of
https://github.com/home-assistant/android
synced 2024-09-19 08:01:31 +00:00
Last Notification Sensor (#1018)
* Initial work on last notification sensor. * Add allow list for packages. * Add way to get sensor setting in common place. * ktLint * Add isEnabled check.
This commit is contained in:
parent
3c0f1a8dce
commit
989229f2d8
|
@ -113,6 +113,13 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service android:name=".sensors.NotificationSensorManager"
|
||||||
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.notification.NotificationListenerService"/>
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".sensors.LocationSensorManager"
|
android:name=".sensors.LocationSensorManager"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package io.homeassistant.companion.android.sensors
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
|
import android.service.notification.NotificationListenerService
|
||||||
|
import android.service.notification.StatusBarNotification
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import io.homeassistant.companion.android.R
|
||||||
|
|
||||||
|
class NotificationSensorManager : NotificationListenerService(), SensorManager {
|
||||||
|
companion object {
|
||||||
|
val lastNotification = SensorManager.BasicSensor(
|
||||||
|
"last_notification",
|
||||||
|
"sensor",
|
||||||
|
R.string.basic_sensor_name_last_notification,
|
||||||
|
R.string.sensor_description_last_notification
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override val name: Int
|
||||||
|
get() = R.string.sensor_name_last_notification
|
||||||
|
override val availableSensors: List<SensorManager.BasicSensor>
|
||||||
|
get() = listOf(lastNotification)
|
||||||
|
override val enabledByDefault: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
|
override fun requiredPermissions(sensorId: String): Array<String> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
package io.homeassistant.companion.android.sensors
|
package io.homeassistant.companion.android.sensors
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.provider.Settings
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.MultiSelectListPreference
|
import androidx.preference.MultiSelectListPreference
|
||||||
|
@ -67,7 +70,12 @@ class SensorDetailFragment(
|
||||||
val isEnabled = newState as Boolean
|
val isEnabled = newState as Boolean
|
||||||
|
|
||||||
if (isEnabled && !sensorManager.checkPermission(requireContext(), basicSensor.id)) {
|
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
|
return@setOnPreferenceChangeListener false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.homeassistant.companion.android.R
|
||||||
import io.homeassistant.companion.android.database.AppDatabase
|
import io.homeassistant.companion.android.database.AppDatabase
|
||||||
import io.homeassistant.companion.android.database.sensor.Attribute
|
import io.homeassistant.companion.android.database.sensor.Attribute
|
||||||
import io.homeassistant.companion.android.database.sensor.Sensor
|
import io.homeassistant.companion.android.database.sensor.Sensor
|
||||||
|
import io.homeassistant.companion.android.database.sensor.Setting
|
||||||
|
|
||||||
interface SensorManager {
|
interface SensorManager {
|
||||||
|
|
||||||
|
@ -58,6 +59,24 @@ interface SensorManager {
|
||||||
return true
|
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(
|
fun onSensorUpdated(
|
||||||
context: Context,
|
context: Context,
|
||||||
basicSensor: BasicSensor,
|
basicSensor: BasicSensor,
|
||||||
|
|
|
@ -34,6 +34,7 @@ class SensorReceiver : BroadcastReceiver() {
|
||||||
LocationSensorManager(),
|
LocationSensorManager(),
|
||||||
NetworkSensorManager(),
|
NetworkSensorManager(),
|
||||||
NextAlarmManager(),
|
NextAlarmManager(),
|
||||||
|
NotificationSensorManager(),
|
||||||
PhoneStateSensorManager(),
|
PhoneStateSensorManager(),
|
||||||
PowerSensorManager(),
|
PowerSensorManager(),
|
||||||
PressureSensorManager(),
|
PressureSensorManager(),
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
<string name="basic_sensor_name_geolocation">Geocoded Location</string>
|
<string name="basic_sensor_name_geolocation">Geocoded Location</string>
|
||||||
<string name="basic_sensor_name_interactive">Interactive</string>
|
<string name="basic_sensor_name_interactive">Interactive</string>
|
||||||
<string name="basic_sensor_name_internal_storage">Internal Storage</string>
|
<string name="basic_sensor_name_internal_storage">Internal Storage</string>
|
||||||
|
<string name="basic_sensor_name_last_notification">Last Notification</string>
|
||||||
<string name="basic_sensor_name_last_reboot">Last Reboot</string>
|
<string name="basic_sensor_name_last_reboot">Last Reboot</string>
|
||||||
<string name="basic_sensor_name_location_accurate">Single Accurate Location</string>
|
<string name="basic_sensor_name_location_accurate">Single Accurate Location</string>
|
||||||
<string name="basic_sensor_name_location_background">Background Location</string>
|
<string name="basic_sensor_name_location_background">Background Location</string>
|
||||||
|
@ -217,6 +218,7 @@ like to connect to:</string>
|
||||||
<string name="sensor_description_headphone">Whether or not headphones are plugged into the device</string>
|
<string name="sensor_description_headphone">Whether or not headphones are plugged into the device</string>
|
||||||
<string name="sensor_description_interactive">Whether or not the device is in an interactive state</string>
|
<string name="sensor_description_interactive">Whether or not the device is in an interactive state</string>
|
||||||
<string name="sensor_description_internal_storage">Information about the total and available storage space internally</string>
|
<string name="sensor_description_internal_storage">Information about the total and available storage space internally</string>
|
||||||
|
<string name="sensor_description_last_notification">The details of the last notification.</string>
|
||||||
<string name="sensor_description_last_reboot">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).</string>
|
<string name="sensor_description_last_reboot">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).</string>
|
||||||
<string name="sensor_description_light_sensor">The current level of illuminance</string>
|
<string name="sensor_description_light_sensor">The current level of illuminance</string>
|
||||||
<string name="sensor_description_location_accurate">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.</string>
|
<string name="sensor_description_location_accurate">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.</string>
|
||||||
|
@ -261,6 +263,7 @@ like to connect to:</string>
|
||||||
<string name="sensor_name_dnd">Do Not Disturb Sensor</string>
|
<string name="sensor_name_dnd">Do Not Disturb Sensor</string>
|
||||||
<string name="sensor_name_geolocation">Geolocation Sensors</string>
|
<string name="sensor_name_geolocation">Geolocation Sensors</string>
|
||||||
<string name="sensor_name_headphone">Headphones</string>
|
<string name="sensor_name_headphone">Headphones</string>
|
||||||
|
<string name="sensor_name_last_notification">Notification Sensors</string>
|
||||||
<string name="sensor_name_last_reboot">Last Reboot Sensor</string>
|
<string name="sensor_name_last_reboot">Last Reboot Sensor</string>
|
||||||
<string name="sensor_name_light">Light Sensor</string>
|
<string name="sensor_name_light">Light Sensor</string>
|
||||||
<string name="sensor_name_location">Location Sensors</string>
|
<string name="sensor_name_location">Location Sensors</string>
|
||||||
|
|
Loading…
Reference in a new issue