DEV Community

Cover image for I built an open-source Android app that switches dark mode based on ambient light – Adaptive Theme
Lexip
Lexip

Posted on

I built an open-source Android app that switches dark mode based on ambient light – Adaptive Theme

Howdy and happy new year!

I wanted to share an open-source project of mine, that I’ve been working on in my free time:

Adaptive Theme

It automatically switches between Light and Dark mode using the ambient light sensor - not a fixed schedule. Therefore it optimizes readability, eye comfort, and maybe even battery life.

And it's free, ad-free, and open-source, just like it should be. :)

Play Store: play.google.com/store/apps/details?id=dev.lexip.hecate

GitHub Repo: github.com/xLexip/Adaptive-Theme

Battery Efficiency

To avoid the battery drain with constant sensor polling, the app is entirely passive.

I built an event-driven architecture that only checks the light sensor for a split second immediately after the screen turns on. Zero background polling and activity, since it only reacts to system broadcasts.

This event-driven architecture does only work on Android 14 and above. Below that, the sensors can't be properly read in the receiver.

Setup & Permissions

That's the biggest challenge: The app requires WRITE_SECURE_SETTINGS to change the system theme.

Unfortunately this can't be granted that easy and deters many users. So I've tried to make it as easy as possible and implemented a wizard-based setup flow to help grant this via one of multiple methods:

  • Web Tool (Recommended) – A browser-based setup tool to use with another device. No code or ADB installation required (WebADB). It's at lexip.dev/setup
  • Shizuku – If you have Shizuku installed and configured, you can grant the permission directly within the Adaptive Theme app.
  • Root – If your device is rooted, you can grant the permission with one tap inside the app.
  • Manual ADB – If you have ADB installed on your computer, you can run the ADB command manually.

Tech Stack & Architecture

  • UI: Jetpack Compose with Material 3 / Material You. I've tried to rebuild the system settings look in my app (stock/Pixel), hope you like it.
  • Architecture: MVVM with Single-Activity pattern.
  • Concurrency & Streams: Kotlin Coroutines and Flows for reactive state management.
  • Persistence: Jetpack DataStore for type-safe settings storage.

Build Flavors

I maintain two distinct build flavors to keep the core app FOSS-compliant:

Play Store: Does includes Firebase (proprietary, crash logs etc.).

FOSS (GitHub Releases, etc.): Completely clean build with no proprietary blobs or trackers at all.


I’m curious to hear your thoughts and opinions!

Let me know if you encounter any bugs or have ideas for new features. I'll be around to answer questions!

Top comments (0)