Приложение на .NET MAUI (Android), которое управляет яркостью экрана за пределами системных ограничений: затемняет экран полупрозрачным чёрным оверлеем или «осветляет» его белым оверлеем поверх максимальной системной яркости.
| Значение | Что происходит |
|---|---|
| −100 … −1 | Системная яркость ставится на минимум, а поверх всего экрана рисуется тёмный оверлей. Прозрачность растёт с −1 до −100, максимум 95% (MaxDarkAlpha) — экран никогда не становится полностью чёрным и остаётся читаемым. |
| 0 … 100 | Регулируется системная яркость (Settings.System.SCREEN_BRIGHTNESS, 0…255). Автояркость принудительно переводится в ручной режим. Оверлей снят. |
| 101 … 200 | Системная яркость выкручивается на максимум (255), поверх добавётся светлый оверлей до 50% (MaxLightAlpha) — экран «светлее максимума», но не становится сплошным белым пятном. |
- ✅ Ползунок −100…200 в самом простом стандартном интерфейсе (без кастомных стилей).
- ✅ Кнопка «Сброс» на главном экране — аналог «Сброс» из уведомления (значение 0).
- ✅ Обновление состояния: свайп вниз (
RefreshView) и кнопка со стрелками в тулбаре — перечитывают актуальное значение (например, изменённое кнопками из уведомления) и состояние разрешений. Также состояние перечитывается каждый раз при возврате на экран. - ✅ Работа в фоне:
foreground-сервис (BrightnessService) держит оверлей, даже когда приложение закрыто. Значение сохраняется (Preferences) и переживает перезапуск. - ✅ Управление из шторки уведомлений: постоянное уведомление с кнопками «−», «+» (шаг 5), «Сброс» (в 0) и «Выход» (снять оверлей и остановить сервис). Тап по уведомлению открывает приложение.
Ползунок в само уведомление не кладём намеренно:
RemoteViewsне умеет надёжно сообщать прогрессSeekBar. Кнопки — штатный «примитивный» механизм системы. - ✅ Все разрешения запрашиваются кнопками прямо из приложения (открываются соответствующие системные настройки).
BrightnessControl/
├─ BrightnessControl.csproj # net10.0-android, MAUI single project
├─ App.xaml / App.xaml.cs # точка входа, без Shell и без кастомных стилей
├─ MainPage.xaml / .cs # ползунок, кнопки разрешений, статус сервиса
├─ MauiProgram.cs
├─ Platforms/Android/
│ ├─ AndroidManifest.xml # разрешения: SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, FOREGROUND_SERVICE_SPECIAL_USE…
│ ├─ MainActivity.cs # запуск + запрос разрешения на уведомления (Android 13+)
│ ├─ MainApplication.cs
│ ├─ BrightnessController.cs # ЯДРО: оверлей (WindowManager), системная яркость, разрешения
│ ├─ BrightnessService.cs # foreground-сервис + уведомление с кнопками
│ ├─ NotificationActionReceiver.cs# приём нажатий кнопок уведомления
│ └─ Resources/ # иконка уведомления, цвета
└─ Resources/ # иконка приложения, сплэш
- Установите .NET 10 SDK и рабочую нагрузку MAUI:
(или Visual Studio с компонентом «.NET Multi-platform App UI»).
dotnet workload install maui-android
- Подключите устройство (отладка по USB) или запустите эмулятор (API 26+).
- Запуск:
cd BrightnessControl dotnet build -t:Run -f net10.0-android
- Уведомления — запрашиваются автоматически при первом запуске (нужны для кнопки в шторке, без них сервис на Android 13+ будет работать «вслепую»).
- «Наложение поверх других окон» — кнопка на главном экране откроет системную страницу приложения, включите переключатель. Без него оверлей невозможен, ползунок заблокирован.
- «Изменение системных настроек» — вторая кнопка. Нужно только для зоны 0–100 (системная яркость). Затемнение/осветление работают и без него.
- Подвигайте ползунок — запустится фоновый сервис, в шторке появится уведомление.
Всё в Platforms/Android/BrightnessController.cs:
MaxDarkAlpha(0.95) — насколько тёмным может стать экран;MaxLightAlpha(0.50) — насколько «белым»;Step(5) — шаг кнопок «−/+» в уведомлении;- логика зон — метод
Apply(); - множитель системной яркости
2.55(перевод 0–100 → 0–255); - внешний вид ползунка (толщина трека ~10dp, бегунок ~26dp, цвета) — маппинг
WideSliderвMauiProgram.cs+ свойстваMinimumTrackColor/MaximumTrackColor/ThumbColorвMainPage.xaml.
- Только Android: iOS не позволяет рисовать поверх других приложений, на Windows механизм принципиально другой.
- Оверлей накрывает все приложения; статус-бар и панель навигации на части прошивок остаются незатемнёнными (их рисует сама система поверх всех окон).
- Оверлей затемняет и само приложение в том числе — так работают все экранные диммеры.
- Режим автояркости при управлении 0–100 принудительно отключается (иначе система игнорирует ручное значение). Вернуть его можно в настройках экрана.
- Прошивки с агрессивной экономией энергии (Xiaomi/Huawei/Samsung и т.п.) могут убивать фоновые сервисы — добавьте приложение в исключения оптимизации батареи.
- Кнопка «Выход» снимает оверлей, но не возвращает системную яркость к прежнему значению — это осознанное упрощение.
- Проект рассчитан на .NET 10 (
net10.0-android). Если у вас другой мажорный .NET, поменяйтеTargetFrameworksв.csproj(например,net9.0-androidилиnet8.0-android). Для .NET 8 вBrightnessService.csпотребуется: в атрибуте[Service]использоватьServiceType.SpecialUse, а вStartForeground— литерал(ServiceInfoFlags)0x40000000вместоServiceInfoFlags.SpecialUse. - В привязках .NET 10 свойство
Intent.Actionстало только для чтения — везде используется методintent.SetAction(...). Если правите код, присваиватьintent.Action = ...нельзя (CS0200). - Тип
ServiceInfoFlagsв .NET 10 существует одновременно вAndroid.AppиAndroid.Content.PM(CS0104), поэтому в коде он указан полностью квалифицированным:Android.Content.PM.ServiceInfoFlags.SpecialUse.