From bdfd64029484abd2f3b61b1239c6cd3835e82722 Mon Sep 17 00:00:00 2001 From: Sergey Volkov Date: Sun, 27 Mar 2022 16:18:09 +0300 Subject: [PATCH] fix(android): problems with "userinterfacestyle" event (#13265) use TiApplication.onConfigurationChanged instead of BroadcastReceiver fix #13264 --- .../java/ti/modules/titanium/ui/UIModule.java | 69 ++++++++----------- .../appcelerator/titanium/TiApplication.java | 33 +++++++++ 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java b/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java index c6023caf288..62a240eb6fc 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java @@ -23,10 +23,6 @@ import org.appcelerator.titanium.util.TiUIHelper; import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; @@ -36,12 +32,15 @@ import android.view.View; import android.webkit.WebViewClient; import android.widget.Toast; + +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatDelegate; @Kroll.module -public class UIModule extends KrollModule +public class UIModule extends KrollModule implements TiApplication.ConfigurationChangedListener { private static final String TAG = "TiUIModule"; + private int lastEmittedStyle; @Kroll.constant public static final int RETURN_KEY_TYPE_ACTION = 0; @@ -436,16 +435,13 @@ public class UIModule extends KrollModule protected static final int MSG_LAST_ID = KrollProxy.MSG_LAST_ID + 101; - private UIModule.Receiver broadcastReceiver; - public UIModule() { super(); // Register the module's broadcast receiver. - this.broadcastReceiver = new UIModule.Receiver(this); - TiApplication.getInstance().registerReceiver(broadcastReceiver, - new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)); + TiApplication.addConfigurationChangeListener(this); + lastEmittedStyle = getUserInterfaceStyle(); // Set up a listener to be invoked when the JavaScript runtime is about to be terminated/disposed. KrollRuntime.addOnDisposingListener(new KrollRuntime.OnDisposingListener() { @@ -454,9 +450,6 @@ public void onDisposing(KrollRuntime runtime) { // Remove this listener from the runtime's static collection. KrollRuntime.removeOnDisposingListener(this); - - // Unregister this module's broadcast receviers. - TiApplication.getInstance().unregisterReceiver(broadcastReceiver); } }); } @@ -561,8 +554,8 @@ public void setOverrideUserInterfaceStyle(int styleId) // Change the night mode. AppCompatDelegate.setDefaultNightMode(nightModeId); - // Fire a "userinterfacestyle" change event via our broadcast receiver. - this.broadcastReceiver.onReceive(TiApplication.getInstance(), null); + // Fire a "userinterfacestyle" change event. + this.onConfigurationChanged(TiApplication.getInstance().getResources().getConfiguration()); // Force our top-most activity apply the assigned night mode. // Note: Works-around a Google bug where it doesn't always call the activity's onNightModeChanged() method. @@ -575,12 +568,7 @@ public void setOverrideUserInterfaceStyle(int styleId) @Kroll.getProperty public int getUserInterfaceStyle() { - int styleId = getOverrideUserInterfaceStyle(); - if (styleId == Configuration.UI_MODE_NIGHT_UNDEFINED) { - Configuration config = TiApplication.getInstance().getResources().getConfiguration(); - styleId = config.uiMode & Configuration.UI_MODE_NIGHT_MASK; - } - return styleId; + return getUserInterfaceStyle(TiApplication.getInstance().getResources().getConfiguration()); } @Override @@ -589,30 +577,27 @@ public String getApiName() return "Ti.UI"; } - private static class Receiver extends BroadcastReceiver + private int getUserInterfaceStyle(@NonNull Configuration config) + { + int styleId = getOverrideUserInterfaceStyle(); + if (styleId == Configuration.UI_MODE_NIGHT_UNDEFINED) { + styleId = config.uiMode & Configuration.UI_MODE_NIGHT_MASK; + } + return styleId; + } + + @Override + public void onConfigurationChanged(@NonNull Configuration config) { - private UIModule module; - private int lastEmittedStyle; - - public Receiver(UIModule module) - { - super(); - this.module = module; - lastEmittedStyle = this.module.getUserInterfaceStyle(); + int currentMode = getUserInterfaceStyle(config); + if (currentMode == lastEmittedStyle) { + return; } + lastEmittedStyle = currentMode; - @Override - public void onReceive(Context context, Intent intent) - { - int currentMode = this.module.getUserInterfaceStyle(); - if (currentMode == lastEmittedStyle) { - return; - } - lastEmittedStyle = currentMode; + KrollDict event = new KrollDict(); + event.put(TiC.PROPERTY_VALUE, lastEmittedStyle); + fireEvent(TiC.EVENT_USER_INTERFACE_STYLE, event); - KrollDict event = new KrollDict(); - event.put(TiC.PROPERTY_VALUE, lastEmittedStyle); - this.module.fireEvent(TiC.EVENT_USER_INTERFACE_STYLE, event); - } } } diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java index 7f8b0cd168b..eabe8271b55 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java @@ -13,10 +13,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; import android.os.Looper; import android.os.SystemClock; import android.util.DisplayMetrics; import android.view.accessibility.AccessibilityManager; + +import androidx.annotation.NonNull; + import com.appcelerator.aps.APSAnalytics; import com.appcelerator.aps.APSAnalyticsMeta; @@ -99,6 +103,7 @@ public abstract class TiApplication extends Application implements KrollApplicat public static AtomicBoolean isActivityTransition = new AtomicBoolean(false); protected static ArrayList activityTransitionListeners = new ArrayList<>(); + protected static ArrayList configurationChangedListeners = new ArrayList<>(); protected static TiWeakList activityStack = new TiWeakList<>(); public interface ActivityTransitionListener { @@ -123,6 +128,27 @@ public static void updateActivityTransitionState(boolean state) } } + public interface ConfigurationChangedListener { + void onConfigurationChanged(@NonNull Configuration newConfig); + } + + public static void addConfigurationChangeListener(ConfigurationChangedListener a) + { + configurationChangedListeners.add(a); + } + + public static void removeConfigurationChangedListener(ConfigurationChangedListener a) + { + configurationChangedListeners.remove(a); + } + + public static void notifyConfigurationChangedListeners(@NonNull Configuration newConfig) + { + for (int i = 0; i < configurationChangedListeners.size(); ++i) { + configurationChangedListeners.get(i).onConfigurationChanged(newConfig); + } + } + public static long START_TIME_MS = 0; public TiApplication() @@ -270,6 +296,13 @@ public Activity getCurrentActivity() return null; } + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) + { + super.onConfigurationChanged(newConfig); + TiApplication.notifyConfigurationChangedListeners(newConfig); + } + /** * @return root activity if exists. If root activity doesn't exist, returns current activity if exists. Otherwise returns null. */