Automatically change your app’s theme depending on the time of day
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:
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:
- Get the user’s current location
- Calculate sunrise/sunset times at the user’s location
- 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:
Parsing the stored preference to obtain a Location
object is done using this method:
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:
Finally, our code can simply call updateDeviceLocationIfNeeded()
from a convenient place, such as the onCreate()
method of your 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:
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:
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
:
If you wish to call setDayNightTheme()
from a method other than onCreate()
, you’ll have to include additional code to recreate the Activity
:
And that’s everything! Now you can include an Auto theme option in your next app.