Merge pull request #22862 from brave/toggle_window_android

[Android] Toggle window
This commit is contained in:
Tapan Modh
2024-04-26 10:22:47 +05:30
committed by GitHub
19 changed files with 684 additions and 30 deletions
+24
View File
@@ -525,6 +525,30 @@
public <init>(...);
}
-keep class org.chromium.chrome.browser.multiwindow.MultiInstanceManagerApi31 {
*** mInstanceId;
moveTabAction(...);
handleMenuOrKeyboardAction(...);
<init>(...);
}
-keep class org.chromium.chrome.browser.multiwindow.BraveMultiInstanceManagerApi31 {
<init>(...);
}
-keep class org.chromium.chrome.browser.multiwindow.MultiWindowUtils {
*** shouldShowManageWindowsMenu(...);
*** isOpenInOtherWindowSupported(...);
*** isMoveToOtherWindowSupported(...);
*** canEnterMultiWindowMode(...);
<init>(...);
}
-keep class org.chromium.chrome.browser.multiwindow.BraveMultiWindowUtils {
*** shouldShowManageWindowsMenu(...);
public <init>(...);
}
-keep class org.chromium.chrome.browser.notifications.permissions.NotificationPermissionRationaleDialogController {
*** wrapDialogDismissalCallback(...);
public <init>(...);
@@ -54,6 +54,8 @@ public final class BravePreferenceKeys {
public static final String BRAVE_CLEAR_ON_EXIT = "clear_on_exit";
public static final String BRAVE_QUICK_ACTION_SEARCH_AND_BOOKMARK_WIDGET_TILES =
"org.chromium.chrome.browser.widget.quickactionsearchandbookmark.QuickActionSearchAndBookmarkWidgetProvider.TILES";
public static final String ENABLE_MULTI_WINDOWS = "enable_multi_windows";
public static final String ENABLE_MULTI_WINDOWS_UPGRADE = "enable_multi_windows_upgrade";
public static final String BRAVE_LEO_AUTOCOMPLETE =
"org.chromium.chrome.browser.Brave_Leo_AutoComplete";
@@ -123,6 +123,9 @@ import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
import org.chromium.chrome.browser.informers.BraveSyncAccountDeletedInformer;
import org.chromium.chrome.browser.misc_metrics.MiscAndroidMetricsConnectionErrorHandler;
import org.chromium.chrome.browser.misc_metrics.MiscAndroidMetricsFactory;
import org.chromium.chrome.browser.multiwindow.BraveMultiWindowUtils;
import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.notifications.BraveNotificationWarningDialog;
import org.chromium.chrome.browser.notifications.permissions.NotificationPermissionController;
import org.chromium.chrome.browser.notifications.retention.RetentionNotificationUtil;
@@ -1188,6 +1191,17 @@ public abstract class BraveActivity extends ChromeActivity
calender.add(Calendar.DATE, DAYS_7);
BraveRewardsHelper.setRewardsOnboardingIconTiming(calender.getTimeInMillis());
}
// Check multiwindow toggle for upgrade case
if (!isFirstInstall
&& !BraveMultiWindowUtils.isCheckUpgradeEnableMultiWindows()
&& MultiWindowUtils.getInstanceCount() > 1
&& !BraveMultiWindowUtils.shouldEnableMultiWindows()) {
BraveMultiWindowUtils.setCheckUpgradeEnableMultiWindows(true);
BraveMultiWindowUtils.updateEnableMultiWindows(true);
} else if (!BraveMultiWindowUtils.isCheckUpgradeEnableMultiWindows()) {
BraveMultiWindowUtils.setCheckUpgradeEnableMultiWindows(true);
}
}
@Override
@@ -2232,4 +2246,10 @@ public abstract class BraveActivity extends ChromeActivity
public RootUiCoordinator getRootUiCoordinator() {
return mRootUiCoordinator;
}
public MultiInstanceManager getMultiInstanceManager() {
return (MultiInstanceManager)
BraveReflectionUtil.getField(
ChromeTabbedActivity.class, "mMultiInstanceManager", this);
}
}
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthController;
import org.chromium.chrome.browser.layouts.LayoutStateProvider;
import org.chromium.chrome.browser.multiwindow.BraveMultiWindowUtils;
import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
import org.chromium.chrome.browser.readaloud.ReadAloudController;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -121,4 +122,15 @@ public class BraveAppMenuPropertiesDelegateImpl extends AppMenuPropertiesDelegat
}
}
}
@Override
protected boolean shouldShowNewWindow() {
return BraveMultiWindowUtils.shouldEnableMultiWindows() && super.shouldShowNewWindow();
}
@Override
protected boolean shouldShowMoveToOtherWindow() {
return BraveMultiWindowUtils.shouldEnableMultiWindows()
&& super.shouldShowMoveToOtherWindow();
}
}
@@ -0,0 +1,94 @@
/* Copyright (c) 2024 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
package org.chromium.chrome.browser.multiwindow;
import android.app.Activity;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManagerProvider;
import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
import org.chromium.ui.modaldialog.ModalDialogManager;
class BraveMultiInstanceManagerApi31 extends MultiInstanceManagerApi31 {
private static final String TAG = "MultiInstanceApi31";
private int mInstanceId;
private boolean mIsMoveTabsFromSettings;
BraveMultiInstanceManagerApi31(
Activity activity,
ObservableSupplier<TabModelOrchestrator> tabModelOrchestratorSupplier,
MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
ActivityLifecycleDispatcher activityLifecycleDispatcher,
ObservableSupplier<ModalDialogManager> modalDialogManagerSupplier,
MenuOrKeyboardActionController menuOrKeyboardActionController) {
super(
activity,
tabModelOrchestratorSupplier,
multiWindowModeStateDispatcher,
activityLifecycleDispatcher,
modalDialogManagerSupplier,
menuOrKeyboardActionController);
}
@Override
public boolean handleMenuOrKeyboardAction(int id, boolean fromMenu) {
if (id == org.chromium.chrome.R.id.move_to_other_window_menu_id) {
mIsMoveTabsFromSettings = !fromMenu;
}
return super.handleMenuOrKeyboardAction(id, fromMenu);
}
@Override
public void moveTabAction(InstanceInfo info, Tab tab, int tabAtIndex) {
super.moveTabAction(info, tab, tabAtIndex);
if (mIsMoveTabsFromSettings) {
mIsMoveTabsFromSettings = false;
TabModelSelector selector =
TabWindowManagerSingleton.getInstance().getTabModelSelectorById(mInstanceId);
if (selector.getTotalTabCount() == 0) {
closeInstance(mInstanceId, INVALID_TASK_ID);
}
if (MultiWindowUtils.getInstanceCount() == 1) {
BraveMultiWindowUtils.updateEnableMultiWindows(false);
} else {
Snackbar snackbar =
Snackbar.make(
mActivity
.getResources()
.getString(R.string.merge_windows_snackbar),
new SnackbarController() {
@Override
public void onDismissNoAction(Object actionData) {}
@Override
public void onAction(Object actionData) {
BraveMultiWindowUtils.mergeWindows(null);
}
},
Snackbar.TYPE_ACTION,
Snackbar.UMA_UNKNOWN)
.setAction(
mActivity.getResources().getString(R.string.merge_windows),
null)
.setSingleLine(false)
.setDuration(10000);
SnackbarManager snackbarManager =
SnackbarManagerProvider.from(tab.getWindowAndroid());
snackbarManager.showSnackbar(snackbar);
}
}
}
}
@@ -0,0 +1,80 @@
/* Copyright (c) 2024 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
package org.chromium.chrome.browser.multiwindow;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import androidx.annotation.NonNull;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.BraveDialogFragment;
public class BraveMultiWindowDialogFragment extends BraveDialogFragment {
private static final String TAG = "MultiWindowDialog";
public interface DismissListener {
void onDismiss();
}
private DismissListener mListener;
public void setDismissListener(DismissListener listener) {
mListener = listener;
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (mListener != null) {
mListener.onDismiss();
}
}
public static BraveMultiWindowDialogFragment newInstance() {
return new BraveMultiWindowDialogFragment();
}
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_brave_multiwindow_dialog, container, false);
if (getDialog() != null && getDialog().getWindow() != null) {
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
}
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
Button mergeBtn = view.findViewById(R.id.btn_merge);
mergeBtn.setOnClickListener(
btn -> {
BraveMultiWindowUtils.mergeWindows(getActivity());
dismiss();
});
if (MultiWindowUtils.isMultiInstanceApi31Enabled()) {
Button closeBtn = view.findViewById(R.id.btn_close);
closeBtn.setVisibility(View.VISIBLE);
closeBtn.setOnClickListener(
btn -> {
BraveMultiWindowUtils.closeWindows();
dismiss();
});
}
}
}
@@ -0,0 +1,109 @@
/* Copyright (c) 2024 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
package org.chromium.chrome.browser.multiwindow;
import android.app.Activity;
import android.content.Intent;
import org.chromium.base.BravePreferenceKeys;
import org.chromium.base.Log;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.app.BraveActivity;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import java.util.List;
public class BraveMultiWindowUtils extends MultiWindowUtils {
private static final String TAG = "MultiWindowUtils";
public BraveMultiWindowUtils() {
super();
}
public static boolean shouldShowManageWindowsMenu() {
return shouldEnableMultiWindows() && MultiWindowUtils.shouldShowManageWindowsMenu();
}
@Override
public boolean isOpenInOtherWindowSupported(Activity activity) {
return shouldEnableMultiWindows() && super.isOpenInOtherWindowSupported(activity);
}
@Override
public boolean isMoveToOtherWindowSupported(
Activity activity, TabModelSelector tabModelSelector) {
return shouldEnableMultiWindows()
&& super.isMoveToOtherWindowSupported(activity, tabModelSelector);
}
@Override
public boolean canEnterMultiWindowMode(Activity activity) {
return shouldEnableMultiWindows() && super.canEnterMultiWindowMode(activity);
}
public static boolean shouldEnableMultiWindows() {
return ChromeSharedPreferences.getInstance()
.readBoolean(BravePreferenceKeys.ENABLE_MULTI_WINDOWS, false);
}
public static void updateEnableMultiWindows(boolean isEnable) {
ChromeSharedPreferences.getInstance()
.writeBoolean(BravePreferenceKeys.ENABLE_MULTI_WINDOWS, isEnable);
}
public static boolean isCheckUpgradeEnableMultiWindows() {
return ChromeSharedPreferences.getInstance()
.readBoolean(BravePreferenceKeys.ENABLE_MULTI_WINDOWS_UPGRADE, false);
}
public static void setCheckUpgradeEnableMultiWindows(boolean isUpgradeCheck) {
ChromeSharedPreferences.getInstance()
.writeBoolean(BravePreferenceKeys.ENABLE_MULTI_WINDOWS_UPGRADE, isUpgradeCheck);
}
public static void mergeWindows(Activity activity) {
try {
MultiInstanceManager multiInstanceManager =
BraveActivity.getBraveActivity().getMultiInstanceManager();
if (multiInstanceManager != null) {
multiInstanceManager.handleMenuOrKeyboardAction(
org.chromium.chrome.R.id.move_to_other_window_menu_id, false);
if (activity != null) {
Intent intent = new Intent(activity, ChromeTabbedActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setAction(Intent.ACTION_VIEW);
activity.startActivity(intent);
}
}
} catch (BraveActivity.BraveActivityNotFoundException e) {
Log.e(TAG, "get BraveActivity exception", e);
}
}
public static void closeWindows() {
try {
MultiInstanceManager multiInstanceManager =
BraveActivity.getBraveActivity().getMultiInstanceManager();
if (multiInstanceManager != null) {
if (multiInstanceManager instanceof MultiInstanceManagerApi31) {
MultiInstanceManagerApi31 multiInstanceManagerApi31 =
((MultiInstanceManagerApi31) multiInstanceManager);
List<InstanceInfo> allInstances = multiInstanceManagerApi31.getInstanceInfo();
if (allInstances != null && allInstances.size() > 1) {
for (int i = 1; i < allInstances.size(); i++) {
multiInstanceManagerApi31.closeInstance(
allInstances.get(i).instanceId, allInstances.get(i).taskId);
}
}
}
}
} catch (BraveActivity.BraveActivityNotFoundException e) {
Log.e(TAG, "get BraveActivity exception", e);
}
}
}
@@ -14,6 +14,7 @@ import androidx.preference.Preference;
import org.chromium.base.BraveFeatureList;
import org.chromium.base.BravePreferenceKeys;
import org.chromium.base.BuildInfo;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.BraveFeatureUtil;
@@ -21,6 +22,9 @@ import org.chromium.chrome.browser.BraveRelaunchUtils;
import org.chromium.chrome.browser.BraveRewardsNativeWorker;
import org.chromium.chrome.browser.BraveRewardsObserver;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.multiwindow.BraveMultiWindowDialogFragment;
import org.chromium.chrome.browser.multiwindow.BraveMultiWindowUtils;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.night_mode.NightModeUtils;
import org.chromium.chrome.browser.preferences.BravePref;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
@@ -43,17 +47,20 @@ public class AppearancePreferences extends BravePreferenceFragment
public static final String PREF_BRAVE_DISABLE_SHARING_HUB = "brave_disable_sharing_hub";
public static final String PREF_BRAVE_ENABLE_TAB_GROUPS = "brave_enable_tab_groups";
public static final String PREF_BRAVE_ENABLE_SPEEDREADER = "brave_enable_speedreader";
public static final String PREF_ENABLE_MULTI_WINDOWS = "enable_multi_windows";
private BraveRewardsNativeWorker mBraveRewardsNativeWorker;
private boolean mIsTablet;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.prefs_appearance);
SettingsUtils.addPreferencesFromResource(this, R.xml.appearance_preferences);
boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(
ContextUtils.getApplicationContext());
if (isTablet) {
mIsTablet =
DeviceFormFactor.isNonMultiDisplayContextOnTablet(
ContextUtils.getApplicationContext());
if (mIsTablet) {
removePreferenceIfPresent(BravePreferenceKeys.BRAVE_BOTTOM_TOOLBAR_ENABLED_KEY);
}
@@ -69,6 +76,35 @@ public class AppearancePreferences extends BravePreferenceFragment
if (!ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_SPEEDREADER)) {
removePreferenceIfPresent(PREF_BRAVE_ENABLE_SPEEDREADER);
}
if (!shouldShowEnableWindow()) {
removePreferenceIfPresent(PREF_ENABLE_MULTI_WINDOWS);
}
}
// Copied from shouldShowNewWindow() method AppMenuPropertiesDelegateImpl.java
private boolean shouldShowEnableWindow() {
if (BuildInfo.getInstance().isAutomotive) return false;
if (MultiWindowUtils.shouldShowManageWindowsMenu()) return true;
if (MultiWindowUtils.instanceSwitcherEnabled()
&& MultiWindowUtils.isMultiInstanceApi31Enabled()) {
return mIsTablet
|| (!MultiWindowUtils.getInstance()
.isChromeRunningInAdjacentWindow(getActivity())
&& (MultiWindowUtils.getInstance().isInMultiWindowMode(getActivity())
|| MultiWindowUtils.getInstance()
.isInMultiDisplayMode(getActivity())));
} else {
if (MultiWindowUtils.getInstance().areMultipleChromeInstancesRunning(getActivity())) {
return false;
}
return (MultiWindowUtils.getInstance().canEnterMultiWindowMode(getActivity())
&& mIsTablet)
|| MultiWindowUtils.getInstance().isInMultiWindowMode(getActivity())
|| MultiWindowUtils.getInstance().isInMultiDisplayMode(getActivity());
}
}
@Override
@@ -152,6 +188,15 @@ public class AppearancePreferences extends BravePreferenceFragment
.getBoolean(BravePref.SPEEDREADER_PREF_ENABLED));
}
}
Preference enableMultiWindow = findPreference(PREF_ENABLE_MULTI_WINDOWS);
if (enableMultiWindow != null) {
enableMultiWindow.setOnPreferenceChangeListener(this);
if (enableMultiWindow instanceof ChromeSwitchPreference) {
((ChromeSwitchPreference) enableMultiWindow)
.setChecked(BraveMultiWindowUtils.shouldEnableMultiWindows());
}
}
}
@Override
@@ -205,6 +250,33 @@ public class AppearancePreferences extends BravePreferenceFragment
UserPrefs.get(ProfileManager.getLastUsedRegularProfile())
.setBoolean(BravePref.SPEEDREADER_PREF_ENABLED, (boolean) newValue);
shouldRelaunch = true;
} else if (PREF_ENABLE_MULTI_WINDOWS.equals(key)) {
if (!(boolean) newValue) {
if (MultiWindowUtils.getInstanceCount() > 1) {
BraveMultiWindowDialogFragment dialogFragment =
BraveMultiWindowDialogFragment.newInstance();
BraveMultiWindowDialogFragment.DismissListener dismissListener =
new BraveMultiWindowDialogFragment.DismissListener() {
@Override
public void onDismiss() {
if (MultiWindowUtils.getInstanceCount() == 1) {
if (preference instanceof ChromeSwitchPreference) {
((ChromeSwitchPreference) preference).setChecked(false);
BraveMultiWindowUtils.updateEnableMultiWindows(false);
}
}
}
};
dialogFragment.setDismissListener(dismissListener);
dialogFragment.show(
getActivity().getSupportFragmentManager(),
"BraveMultiWindowDialogFragment");
return false;
}
}
BraveMultiWindowUtils.updateEnableMultiWindows((boolean) newValue);
}
if (shouldRelaunch) {
BraveRelaunchUtils.askForRelaunch(getActivity());
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2024 The Brave Authors. All rights reserved.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at https://mozilla.org/MPL/2.0/.
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:paddingVertical="16dp"
android:background="@drawable/rounded_bookmark_import_export_dialog_bg">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="16sp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="10dp"
android:text="@string/multi_windows_dialog_title"
android:textColor="@color/bookmark_import_export_dialog_title_color"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/tv_title"
android:layout_marginTop="5dp"
android:text="@string/multi_windows_dialog_summary"
android:textColor="@color/bookmark_import_export_dialog_secondary_color"/>
<android.widget.Button
android:id="@+id/btn_merge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/tv_summary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_close"
android:background="@android:color/transparent"
android:textAllCaps="false"
android:text="@string/merge_windows"
android:textColor="@color/bookmark_import_export_dialog_button_color"
android:textSize="16sp"
style="?android:attr/borderlessButtonStyle"/>
<android.widget.Button
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@id/tv_summary"
app:layout_constraintStart_toEndOf="@id/btn_merge"
app:layout_constraintEnd_toEndOf="parent"
android:background="@android:color/transparent"
android:textAllCaps="false"
android:text="@string/close_windows"
android:textColor="@color/bookmark_import_export_dialog_button_color"
android:textSize="16sp"
android:visibility="gone"
style="?android:attr/borderlessButtonStyle"/>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -44,6 +44,11 @@
android:summary="@string/enable_speedreader_summary"
android:defaultValue="true" />
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
android:key="enable_multi_windows"
android:title="@string/enable_multi_windows_title"
android:summary="@string/enable_multi_windows_summary" />
<Preference
android:fragment="org.chromium.chrome.browser.night_mode.settings.BraveThemePreferences"
android:key="ui_theme"