diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0948ae0a7..12479b462 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,6 +40,8 @@ + diff --git a/app/src/main/java/io/homeassistant/companion/android/notifications/MessagingManager.kt b/app/src/main/java/io/homeassistant/companion/android/notifications/MessagingManager.kt index 83f47c557..d37a51ebf 100644 --- a/app/src/main/java/io/homeassistant/companion/android/notifications/MessagingManager.kt +++ b/app/src/main/java/io/homeassistant/companion/android/notifications/MessagingManager.kt @@ -167,6 +167,8 @@ class MessagingManager @Inject constructor( const val COMMAND_LAUNCH_APP = "command_launch_app" const val COMMAND_PERSISTENT_CONNECTION = "command_persistent_connection" const val COMMAND_STOP_TTS = "command_stop_tts" + const val COMMAND_AUTO_SCREEN_BRIGHTNESS = "command_auto_screen_brightness" + const val COMMAND_SCREEN_BRIGHTNESS_LEVEL = "command_screen_brightness_level" // DND commands const val DND_PRIORITY_ONLY = "priority_only" @@ -243,7 +245,9 @@ class MessagingManager @Inject constructor( COMMAND_UPDATE_SENSORS, COMMAND_LAUNCH_APP, COMMAND_PERSISTENT_CONNECTION, - COMMAND_STOP_TTS + COMMAND_STOP_TTS, + COMMAND_AUTO_SCREEN_BRIGHTNESS, + COMMAND_SCREEN_BRIGHTNESS_LEVEL ) val DND_COMMANDS = listOf(DND_ALARMS_ONLY, DND_ALL, DND_NONE, DND_PRIORITY_ONLY) val RM_COMMANDS = listOf(RM_NORMAL, RM_SILENT, RM_VIBRATE) @@ -529,6 +533,22 @@ class MessagingManager @Inject constructor( } } COMMAND_STOP_TTS -> handleDeviceCommands(jsonData) + COMMAND_AUTO_SCREEN_BRIGHTNESS -> { + if (!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND] in ENABLE_COMMANDS) + handleDeviceCommands(jsonData) + else + mainScope.launch { + sendNotification(jsonData) + } + } + COMMAND_SCREEN_BRIGHTNESS_LEVEL -> { + if (!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND]?.toIntOrNull() != null) + handleDeviceCommands(jsonData) + else + mainScope.launch { + sendNotification(jsonData) + } + } else -> Log.d(TAG, "No command received") } } @@ -894,6 +914,16 @@ class MessagingManager @Inject constructor( COMMAND_STOP_TTS -> { stopTTS() } + COMMAND_AUTO_SCREEN_BRIGHTNESS, COMMAND_SCREEN_BRIGHTNESS_LEVEL -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Settings.System.canWrite(context)) { + if (!processScreenBrightness(data)) + mainScope.launch { sendNotification(data) } + } else + notifyMissingPermission(data[MESSAGE].toString()) + } else if (!processScreenBrightness(data)) + mainScope.launch { sendNotification(data) } + } else -> Log.d(TAG, "No command received") } } @@ -1790,6 +1820,14 @@ class MessagingManager @Inject constructor( context.startActivity(intent) } + @RequiresApi(Build.VERSION_CODES.M) + private fun requestWriteSystemPermission() { + val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS) + intent.data = Uri.parse("package:" + context.packageName) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + context.startActivity(intent) + } + private fun getKeyEvent(key: String): Int { return when (key) { MEDIA_FAST_FORWARD -> KeyEvent.KEYCODE_MEDIA_FAST_FORWARD @@ -1996,6 +2034,27 @@ class MessagingManager @Inject constructor( WebsocketManager.start(context) } + private fun processScreenBrightness(data: Map): Boolean { + val command = data[COMMAND] + val contentResolver = context.contentResolver + val success = Settings.System.putInt( + contentResolver, + if (data[MESSAGE].toString() == COMMAND_SCREEN_BRIGHTNESS_LEVEL) + Settings.System.SCREEN_BRIGHTNESS + else + Settings.System.SCREEN_BRIGHTNESS_MODE, + if (data[MESSAGE].toString() == COMMAND_SCREEN_BRIGHTNESS_LEVEL) + command!!.toInt().coerceIn(0, 255) + else { + if (command == TURN_ON) + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC + else + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL + } + ) + return success + } + private fun notifyMissingPermission(type: String) { val appManager = context.getSystemService() @@ -2030,6 +2089,11 @@ class MessagingManager @Inject constructor( } navigateAppDetails() } + COMMAND_SCREEN_BRIGHTNESS_LEVEL, COMMAND_AUTO_SCREEN_BRIGHTNESS -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + requestWriteSystemPermission() + } + } } } } diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/DisplaySensorManager.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/DisplaySensorManager.kt new file mode 100755 index 000000000..3a8cb5dd4 --- /dev/null +++ b/app/src/main/java/io/homeassistant/companion/android/sensors/DisplaySensorManager.kt @@ -0,0 +1,74 @@ +package io.homeassistant.companion.android.sensors + +import android.content.Context +import android.provider.Settings +import android.util.Log +import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.R as commonR + +class DisplaySensorManager : SensorManager { + companion object { + private const val TAG = "ScreenBrightness" + + val screenBrightness = SensorManager.BasicSensor( + "screen_brightness", + "sensor", + commonR.string.basic_sensor_name_screen_brightness, + commonR.string.sensor_description_screen_brightness, + statelessIcon = "mdi:brightness-6" + ) + } + + override fun docsLink(): String { + return "https://companion.home-assistant.io/docs/core/sensors#screen-brightness-sensor" + } + + override val enabledByDefault: Boolean + get() = false + override val name: Int + get() = commonR.string.sensor_name_display_sensors + + override fun getAvailableSensors(context: Context): List { + return listOf(screenBrightness) + } + + override fun requiredPermissions(sensorId: String): Array { + return emptyArray() + } + + override fun requestSensorUpdate( + context: Context + ) { + updateScreenBrightness(context) + } + + private fun updateScreenBrightness(context: Context) { + if (!isEnabled(context, screenBrightness.id)) + return + + var brightness = 0 + var auto = false + + try { + brightness = + Settings.System.getInt(context.contentResolver, Settings.System.SCREEN_BRIGHTNESS) + auto = Settings.System.getInt( + context.contentResolver, + Settings.System.SCREEN_BRIGHTNESS_MODE + ) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC + } catch (e: Exception) { + Log.e(TAG, "Unable to get screen brightness settings", e) + } + + val icon = if (auto) "mdi:brightness-auto" else screenBrightness.statelessIcon + onSensorUpdated( + context, + screenBrightness, + brightness, + icon, + mapOf( + "automatic" to auto + ) + ) + } +} 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 daa434587..0d3a6cbaa 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 @@ -37,6 +37,7 @@ class SensorReceiver : SensorReceiverBase() { AudioSensorManager(), BatterySensorManager(), BluetoothSensorManager(), + DisplaySensorManager(), DNDSensorManager(), DynamicColorSensorManager(), DevicePolicyManager(), diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 37e377254..c4c5cf483 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -919,4 +919,7 @@ Accent Color A hexadecimal color value for the dynamic accent color used in the device theme Dynamic Color + Screen Brightness + The current screen brightness on the device, an attribute also indicates if auto-brightness is enabled + Display Sensors