Automatically change your app’s theme depending on the time of day

Gavin Wright
3 min readMar 5, 2021

--

Android has built-in functionality for accomplishing automatic theme switching at sunrise and sunset: AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_TIME). But the MODE_NIGHT_AUTO_TIME constant is now deprecated, with Google recommending against its usage while not providing any rationale for its decision:

Deprecation notice for MODE_NIGHT_AUTO_THEME constant

This is no big loss, as the functionality never worked very well anyways. Theme switching never seemed to occur exactly at sunrise or sunset, often missing the mark by as much as an hour. But, more crucially, the theme switching wouldn’t always propagate to all Views in the layout. Instead, an unlucky user might be presented with an awkward combination of day and night themes that would persist until force-closing the app. We can do better.

Before we begin, your app should already support manually switching between light and dark themes. See here for more information. Then we can get to work implementing automatic theme switching. Broadly, this will involve three different tasks:

  1. Get the user’s current location
  2. Calculate sunrise/sunset times at the user’s location
  3. Set the app’s theme based on the current time of day

First, we’ll get the user’s current location. Explaining every aspect of this process is outside the scope of this article, so see here if you need more help with this. For simplicity, let’s just assume you’ve fetched the location and stored it into SharedPreferences as shown below. Note that we store a preference with the key KEY_LOCATION_UPDATE_RESULT, and its value is a string containing the current time, latitude, and longitude separated by commas:

Store the current location and timestamp into SharedPreferences

Parsing the stored preference to obtain a Location object is done using this method:

Parse the location data from the string stored in SharedPreferences and create a Location object out of it

We’ll want to periodically update the KEY_LOCATION_UPDATE_RESULT value to account for the user changing locations. We can trigger this update using the following method:

Check if stored user location is stale, and update it if needed.

Finally, our code can simply call updateDeviceLocationIfNeeded() from a convenient place, such as the onCreate() method of your Activity:

Call updateDeviceLocationIfNeeded() from onCreate() of Activity

Now that the user’s location is being stored, we can use it to calculate the sunrise/sunset times for that location. For this task, we’ll use code from sunrisesunsetlib-java. Just copy the following classes into your project:

  1. SolarEventCalculator.java
  2. SunriseSunsetCalculator.java
  3. Zenith.java

These classes will do all the calculations for us in the final step.

Finally, we can use our calculated sunrise/sunset times to actually set the app’s theme:

Set the current app theme programmatically

But we must take special care in choosing when to call the above setDayNightTheme() method. It must be called before the super() call in onCreate() of our Activity , or else we’ll be forced to recreate the Activity :

Calling setDayNightTheme() from onCreate()

If you wish to call setDayNightTheme() from a method other than onCreate() , you’ll have to include additional code to recreate the Activity :

Calling setDayNightTheme() from another method

And that’s everything! Now you can include an Auto theme option in your next app.

--

--