diff options
Diffstat (limited to 'app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java')
-rw-r--r-- | app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java b/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java new file mode 100644 index 00000000..250cf0a7 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java @@ -0,0 +1,76 @@ +/* + * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package com.wireguard.android.activity; + +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.app.AppCompatDelegate; +import android.util.Log; + +import java.lang.reflect.Field; + +public abstract class ThemeChangeAwareActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = "WireGuard/" + ThemeChangeAwareActivity.class.getSimpleName(); + + private static Resources lastResources; + private static boolean lastDarkMode; + private static synchronized void invalidateDrawableCache(final Resources resources, final boolean darkMode) { + if (resources == lastResources && darkMode == lastDarkMode) + return; + + try { + Field f; + Object o = resources; + try { + f = o.getClass().getDeclaredField("mResourcesImpl"); + f.setAccessible(true); + o = f.get(o); + } catch (final Exception ignored) { } + f = o.getClass().getDeclaredField("mDrawableCache"); + f.setAccessible(true); + o = f.get(o); + try { + o.getClass().getMethod("onConfigurationChange", int.class).invoke(o, -1); + } catch (final Exception ignored) { + o.getClass().getMethod("clear").invoke(o); + } + } catch (final Exception e) { + Log.e(TAG, "Failed to flush drawable cache", e); + } + + lastResources = resources; + lastDarkMode = darkMode; + } + + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); + } + + @Override + protected void onDestroy() { + PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); + super.onDestroy(); + } + + @Override + public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) { + if ("dark_theme".equals(key)) { + final boolean darkMode = sharedPreferences.getBoolean(key, false); + AppCompatDelegate.setDefaultNightMode( + sharedPreferences.getBoolean(key, false) ? + AppCompatDelegate.MODE_NIGHT_YES : + AppCompatDelegate.MODE_NIGHT_NO); + invalidateDrawableCache(getResources(), darkMode); + recreate(); + } + } +} |