diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettings.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettings.java
new file mode 100644
index 000000000..fc56b13fd
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettings.java
@@ -0,0 +1,184 @@
+/* Copyright (C) 2024 José Rebelo
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.XmlRes;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A class that contains the device-specific settings screens for a device. All the integers in this
+ * class correspond to xml resources for preferences.
+ *
+ * This class contains 2 types of screens:
+ * - Root screens - the ones that are displayed in the first page of the device settings activity. These can be
+ * normal preference screens / preferences, or dummy root screens (see {@link DeviceSpecificSettingsScreen}.
+ * - Sub-screens - a screen that is opened when one of the {@link DeviceSpecificSettingsScreen} is clicked.
+ *
+ * There can be an arbitrary number of nested sub-screens, as long as they are all mapped by key in the
+ * subScreens map.
+ *
+ * See the XiaomiCoordinator and ZeppOsCoordinator for example usages.
+ */
+public class DeviceSpecificSettings implements Parcelable {
+ private final List rootScreens = new ArrayList<>();
+ private final Map> subScreens = new LinkedHashMap<>();
+
+ public DeviceSpecificSettings() {
+ }
+
+ public DeviceSpecificSettings(final int[] rootScreens) {
+ for (final int setting : rootScreens) {
+ this.rootScreens.add(setting);
+ }
+ }
+
+ public void addRootScreen(@XmlRes final int screen) {
+ if (!rootScreens.contains(screen)) {
+ rootScreens.add(screen);
+ }
+ }
+
+ public List addRootScreen(final DeviceSpecificSettingsScreen screen) {
+ if (!rootScreens.contains(screen.getXml())) {
+ rootScreens.add(screen.getXml());
+ }
+
+ return addSubScreen(screen, screen.getXml());
+ }
+
+ public List addRootScreen(final DeviceSpecificSettingsScreen screen, final int... subScreens) {
+ final List subScreenScreens = addRootScreen(screen);
+ for (final int subScreen : subScreens) {
+ subScreenScreens.add(subScreen);
+ }
+ return subScreenScreens;
+ }
+
+ public void addRootScreen(final int index, @XmlRes final int screen) {
+ rootScreens.add(index, screen);
+ }
+
+ public List addSubScreen(final DeviceSpecificSettingsScreen rootScreen, final int... screens) {
+ return addSubScreen(rootScreen.getKey(), screens);
+ }
+
+ private List addSubScreen(final String key, final int... screens) {
+ if (!subScreens.containsKey(key)) {
+ subScreens.put(key, new ArrayList<>());
+ }
+
+ final List subscreenPages = Objects.requireNonNull(subScreens.get(key));
+
+ for (final int screen : screens) {
+ if (!subscreenPages.contains(screen)) {
+ subscreenPages.add(screen);
+ }
+ }
+
+ return subscreenPages;
+ }
+
+ public void mergeFrom(final DeviceSpecificSettings deviceSpecificSettings) {
+ for (final Integer rootScreen : deviceSpecificSettings.rootScreens) {
+ addRootScreen(rootScreen);
+ }
+ for (final Map.Entry> e : deviceSpecificSettings.subScreens.entrySet()) {
+ if (!subScreens.containsKey(e.getKey())) {
+ subScreens.put(e.getKey(), new ArrayList<>());
+ }
+
+ for (final int screen : e.getValue()) {
+ Objects.requireNonNull(subScreens.get(e.getKey())).add(screen);
+ }
+ }
+ }
+
+ public List getRootScreens() {
+ return rootScreens;
+ }
+
+ @Nullable
+ public List getScreen(@NonNull final String key) {
+ return subScreens.get(key);
+ }
+
+ public List getAllScreens() {
+ final List allScreens = new ArrayList<>(rootScreens);
+ for (final List screens : subScreens.values()) {
+ allScreens.addAll(screens);
+ }
+ return allScreens;
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public DeviceSpecificSettings createFromParcel(final Parcel in) {
+ final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
+ final int numRootScreens = in.readInt();
+ for (int i = 0; i < numRootScreens; i++) {
+ deviceSpecificSettings.addRootScreen(in.readInt());
+ }
+ final int numSubScreens = in.readInt();
+ for (int i = 0; i < numSubScreens; i++) {
+ final String key = in.readString();
+ final int numScreens = in.readInt();
+ final int[] screens = new int[numScreens];
+ for (int j = 0; j < numScreens; j++) {
+ screens[j] = in.readInt();
+ }
+ deviceSpecificSettings.addSubScreen(key, screens);
+ }
+ return deviceSpecificSettings;
+ }
+
+ @Override
+ public DeviceSpecificSettings[] newArray(final int size) {
+ return new DeviceSpecificSettings[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull final Parcel dest, final int flags) {
+ dest.writeInt(rootScreens.size());
+ for (final Integer rootScreen : rootScreens) {
+ dest.writeInt(rootScreen);
+ }
+ dest.writeInt(subScreens.size());
+ for (final Map.Entry> e : subScreens.entrySet()) {
+ dest.writeString(e.getKey());
+ dest.writeInt(e.getValue().size());
+ for (final Integer s : e.getValue()) {
+ dest.writeInt(s);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java
index 3cc59ceaf..2b7386c20 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsFragment.java
@@ -25,19 +25,19 @@ import android.media.AudioManager;
import android.os.Bundle;
import android.text.InputType;
-import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -59,7 +59,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
-import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
@@ -96,10 +95,15 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
private GBDevice device;
- private void setSettingsFileSuffix(String settingsFileSuffix, @NonNull int[] supportedSettings) {
+ private void setSettingsFileSuffix(String settingsFileSuffix) {
Bundle args = new Bundle();
args.putString("settingsFileSuffix", settingsFileSuffix);
- args.putIntArray("supportedSettings", supportedSettings);
+ setArguments(args);
+ }
+
+ private void setDeviceSpecificSettings(final DeviceSpecificSettings deviceSpecificSettings) {
+ final Bundle args = getArguments() != null ? getArguments() : new Bundle();
+ args.putParcelable("deviceSpecificSettings", deviceSpecificSettings);
setArguments(args);
}
@@ -122,12 +126,11 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
return;
}
String settingsFileSuffix = arguments.getString("settingsFileSuffix", null);
- int[] supportedSettings = arguments.getIntArray("supportedSettings");
- String[] supportedLanguages = arguments.getStringArray("supportedLanguages");
+ DeviceSpecificSettings deviceSpecificSettings = arguments.getParcelable("deviceSpecificSettings");
this.deviceSpecificSettingsCustomizer = arguments.getParcelable("deviceSpecificSettingsCustomizer");
this.device = arguments.getParcelable("device");
- if (settingsFileSuffix == null || supportedSettings == null) {
+ if (settingsFileSuffix == null || deviceSpecificSettings == null) {
return;
}
@@ -136,7 +139,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
if (rootKey == null) {
// we are the main preference screen
boolean first = true;
- for (int setting : supportedSettings) {
+ for (int setting : deviceSpecificSettings.getRootScreens()) {
if (first) {
setPreferencesFromResource(setting, null);
first = false;
@@ -145,16 +148,47 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
}
}
} else {
- // Now, this is ugly: search all the xml files for the rootKey
- for (int setting : supportedSettings) {
- try {
- setPreferencesFromResource(setting, rootKey);
- } catch (Exception ignore) {
- continue;
+ // First attempt to find a known screen for this key
+ final List screenSettings = deviceSpecificSettings.getScreen(rootKey);
+ if (screenSettings != null) {
+ boolean first = true;
+ for (int setting : screenSettings) {
+ if (first) {
+ // Use the root key here to set the root screen, so that the actionbar title gets updated
+ setPreferencesFromResource(setting, rootKey);
+ first = false;
+ } else {
+ addPreferencesFromResource(setting);
+ }
+ }
+ } else {
+ // Now, this is ugly: search all the xml files for the rootKey
+ // This means that this device is using the deprecated getSupportedDeviceSpecificSettings,
+ // or that we're on a sub-screen
+ final List allScreens = deviceSpecificSettings.getAllScreens();
+ for (int setting : allScreens) {
+ try {
+ setPreferencesFromResource(setting, rootKey);
+ } catch (Exception ignore) {
+ continue;
+ }
+ break;
}
- break;
}
}
+
+ // Since all root preference screens are empty, clicking them will not do anything
+ // add on-click listeners
+ for (final DeviceSpecificSettingsScreen value : DeviceSpecificSettingsScreen.values()) {
+ final PreferenceScreen prefScreen = findPreference(value.getKey());
+ if (prefScreen != null) {
+ prefScreen.setOnPreferenceClickListener(p -> {
+ onNavigateToScreen(prefScreen);
+ return true;
+ });
+ }
+ }
+
setChangeListener();
}
@@ -1023,53 +1057,56 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
}
}
- static private void addElementsToList(ArrayList list, int[]... elements){
- for(int[] array : elements){
- for(int item : array){
- list.add(item);
- }
- }
- }
-
static DeviceSpecificSettingsFragment newInstance(GBDevice device, DeviceSettingsActivity.MENU_ENTRY_POINTS applicationSpecificSettings) {
final DeviceCoordinator coordinator = device.getDeviceCoordinator();
- ArrayList supportedSettings = new ArrayList<>();
- String[] supportedLanguages = null;
+
+ final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
if (applicationSpecificSettings.equals(DeviceSettingsActivity.MENU_ENTRY_POINTS.AUTH_SETTINGS)) { //auth settings screen
- supportedSettings.add(R.xml.devicesettings_pairingkey_explanation);
- addElementsToList(supportedSettings, coordinator.getSupportedDeviceSpecificAuthenticationSettings());
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_pairingkey_explanation);
+ for (final int s : coordinator.getSupportedDeviceSpecificAuthenticationSettings()) {
+ deviceSpecificSettings.addRootScreen(s);
+ }
} else { //device/application settings
if (coordinator.getSupportedLanguageSettings(device) != null) {
- supportedSettings.add(R.xml.devicesettings_language_generic);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_language_generic);
+ }
+ DeviceSpecificSettings coordinatorDeviceSettings = coordinator.getDeviceSpecificSettings(device);
+ if (coordinatorDeviceSettings != null) {
+ deviceSpecificSettings.mergeFrom(coordinatorDeviceSettings);
}
- addElementsToList(supportedSettings, coordinator.getSupportedDeviceSpecificSettings(device));
final int[] supportedAuthSettings = coordinator.getSupportedDeviceSpecificAuthenticationSettings();
if (supportedAuthSettings != null && supportedAuthSettings.length > 0) {
- supportedSettings.add(R.xml.devicesettings_header_authentication);
- addElementsToList(supportedSettings, supportedAuthSettings);
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.AUTHENTICATION,
+ supportedAuthSettings
+ );
}
- addElementsToList(
- supportedSettings,
- coordinator.getSupportedDeviceSpecificConnectionSettings(),
- coordinator.getSupportedDeviceSpecificApplicationSettings());
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.CONNECTION,
+ coordinator.getSupportedDeviceSpecificConnectionSettings()
+ );
+
if (coordinator.supportsActivityTracking()) {
- supportedSettings.addAll(Arrays.asList(
- R.xml.devicesettings_activity_info_header,
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.ACTIVITY_INFO,
R.xml.devicesettings_chartstabs,
R.xml.devicesettings_device_card_activity_card_preferences
- ));
+ );
}
- supportedSettings.add(R.xml.devicesettings_settings_third_party_apps);
- }
- int[] supportedSettingsInts = ArrayUtils.toPrimitive(supportedSettings.toArray(new Integer[0]));
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.DEVELOPER,
+ R.xml.devicesettings_settings_third_party_apps
+ );
+ }
final DeviceSpecificSettingsCustomizer deviceSpecificSettingsCustomizer = coordinator.getDeviceSpecificSettingsCustomizer(device);
final String settingsFileSuffix = device.getAddress();
final DeviceSpecificSettingsFragment fragment = new DeviceSpecificSettingsFragment();
- fragment.setSettingsFileSuffix(settingsFileSuffix, supportedSettingsInts);
+ fragment.setSettingsFileSuffix(settingsFileSuffix);
+ fragment.setDeviceSpecificSettings(deviceSpecificSettings);
fragment.setDeviceSpecificSettingsCustomizer(deviceSpecificSettingsCustomizer);
fragment.setDevice(device);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsScreen.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsScreen.java
new file mode 100644
index 000000000..006cb8215
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSpecificSettingsScreen.java
@@ -0,0 +1,51 @@
+/* Copyright (C) 2024 José Rebelo
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
+
+import androidx.annotation.XmlRes;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+
+public enum DeviceSpecificSettingsScreen {
+ ACTIVITY_INFO("pref_screen_activity_info", R.xml.devicesettings_root_activity_info),
+ AUTHENTICATION("pref_screen_authentication", R.xml.devicesettings_root_authentication),
+ CALENDAR("pref_screen_calendar", R.xml.devicesettings_root_calendar),
+ CONNECTION("pref_screen_connection", R.xml.devicesettings_root_connection),
+ DEVELOPER("pref_screen_developer", R.xml.devicesettings_root_developer),
+ DISPLAY("pref_screen_display", R.xml.devicesettings_root_display),
+ NOTIFICATIONS("pref_screen_notifications", R.xml.devicesettings_root_notifications),
+ DATE_TIME("pref_screen_date_time", R.xml.devicesettings_root_date_time),
+ WORKOUT("pref_screen_workout", R.xml.devicesettings_root_workout),
+ ;
+
+ private final String key;
+ @XmlRes
+ private final int xml;
+
+ DeviceSpecificSettingsScreen(final String key, final int xml) {
+ this.key = key;
+ this.xml = xml;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public int getXml() {
+ return xml;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java
index c959a079d..b0f012e13 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java
@@ -51,6 +51,7 @@ import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@@ -590,13 +591,18 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
}
@Override
- public int[] getSupportedDeviceSpecificApplicationSettings() {
+ public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[0];
}
@Override
- public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
- return new int[0];
+ public DeviceSpecificSettings getDeviceSpecificSettings(GBDevice device) {
+ final int[] settings = getSupportedDeviceSpecificSettings(device);
+ if (settings == null || settings.length == 0) {
+ return null;
+ }
+
+ return new DeviceSpecificSettings(settings);
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java
index 16f9ba243..3a4b3df7e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java
@@ -36,6 +36,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import nodomain.freeyourgadget.gadgetbridge.GBException;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@@ -561,13 +562,6 @@ public interface DeviceCoordinator {
*/
int[] getSupportedDeviceSpecificConnectionSettings();
- /**
- * Returns device specific settings related to the application itself
- * charts settings and so on
- * @return int[]
- */
- int[] getSupportedDeviceSpecificApplicationSettings();
-
/**
* Returns device specific settings related to the Auth key
* @return int[]
@@ -576,9 +570,19 @@ public interface DeviceCoordinator {
/**
* Indicates which device specific settings the device supports (not per device type or family, but unique per device).
+ *
+ * @deprecated use getDeviceSpecificSettings
*/
+ @Deprecated
int[] getSupportedDeviceSpecificSettings(GBDevice device);
+ /**
+ * Returns the device-specific settings supported by this specific device. See
+ * {@link DeviceSpecificSettings} for more information
+ */
+ @Nullable
+ DeviceSpecificSettings getDeviceSpecificSettings(GBDevice device);
+
/**
* Returns the {@link DeviceSpecificSettingsCustomizer}, allowing for the customization of the devices specific settings screen.
*/
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
index 663f8b6c9..d65836cbd 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java
@@ -22,8 +22,6 @@ import android.net.Uri;
import androidx.annotation.NonNull;
-import org.apache.commons.lang3.ArrayUtils;
-
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -37,6 +35,8 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@@ -350,150 +350,142 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
* by {@link ZeppOsSettingsCustomizer}.
*/
@Override
- public int[] getSupportedDeviceSpecificSettings(final GBDevice device) {
- final List settings = new ArrayList<>();
+ public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
+ final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
//
// Apps
// TODO: These should go somewhere else
//
- settings.add(R.xml.devicesettings_header_apps);
if (ZeppOsLoyaltyCardService.isSupported(getPrefs(device))) {
- settings.add(R.xml.devicesettings_loyalty_cards);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_loyalty_cards);
}
//
// Time
//
- settings.add(R.xml.devicesettings_header_time);
- //settings.add(R.xml.devicesettings_timeformat);
- settings.add(R.xml.devicesettings_dateformat_2);
+ final List dateTime = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DATE_TIME);
+ //dateTime.add(R.xml.devicesettings_timeformat);
+ dateTime.add(R.xml.devicesettings_dateformat_2);
if (getWorldClocksSlotCount() > 0) {
- settings.add(R.xml.devicesettings_world_clocks);
+ dateTime.add(R.xml.devicesettings_world_clocks);
}
//
// Display
//
- settings.add(R.xml.devicesettings_header_display);
- settings.add(R.xml.devicesettings_huami2021_displayitems);
- settings.add(R.xml.devicesettings_huami2021_shortcuts);
+ final List display = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY);
+ display.add(R.xml.devicesettings_huami2021_displayitems);
+ display.add(R.xml.devicesettings_huami2021_shortcuts);
if (supportsControlCenter()) {
- settings.add(R.xml.devicesettings_huami2021_control_center);
+ display.add(R.xml.devicesettings_huami2021_control_center);
}
if (supportsShortcutCards(device)) {
- settings.add(R.xml.devicesettings_huami2021_shortcut_cards);
+ display.add(R.xml.devicesettings_huami2021_shortcut_cards);
}
- settings.add(R.xml.devicesettings_nightmode);
- settings.add(R.xml.devicesettings_sleep_mode);
- settings.add(R.xml.devicesettings_liftwrist_display_sensitivity_with_smart);
- settings.add(R.xml.devicesettings_password);
- settings.add(R.xml.devicesettings_huami2021_watchface);
- settings.add(R.xml.devicesettings_always_on_display);
- settings.add(R.xml.devicesettings_screen_timeout);
+ display.add(R.xml.devicesettings_nightmode);
+ display.add(R.xml.devicesettings_sleep_mode);
+ display.add(R.xml.devicesettings_liftwrist_display_sensitivity_with_smart);
+ display.add(R.xml.devicesettings_password);
+ display.add(R.xml.devicesettings_huami2021_watchface);
+ display.add(R.xml.devicesettings_always_on_display);
+ display.add(R.xml.devicesettings_screen_timeout);
if (supportsAutoBrightness(device)) {
- settings.add(R.xml.devicesettings_screen_brightness_withauto);
+ display.add(R.xml.devicesettings_screen_brightness_withauto);
} else {
- settings.add(R.xml.devicesettings_screen_brightness);
+ display.add(R.xml.devicesettings_screen_brightness);
}
//
// Health
//
- settings.add(R.xml.devicesettings_header_health);
- settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
- settings.add(R.xml.devicesettings_inactivity_dnd_no_threshold);
- settings.add(R.xml.devicesettings_goal_notification);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_inactivity_dnd_no_threshold);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_notification);
//
// Workout
//
- settings.add(R.xml.devicesettings_header_workout);
+ final List workout = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT);
if (hasGps(device)) {
- settings.add(R.xml.devicesettings_gps_agps);
+ workout.add(R.xml.devicesettings_gps_agps);
} else {
// If the device has GPS, it doesn't report workout start/end to the phone
- settings.add(R.xml.devicesettings_workout_start_on_phone);
- settings.add(R.xml.devicesettings_workout_send_gps_to_band);
+ workout.add(R.xml.devicesettings_workout_start_on_phone);
+ workout.add(R.xml.devicesettings_workout_send_gps_to_band);
}
- settings.add(R.xml.devicesettings_workout_keep_screen_on);
- settings.add(R.xml.devicesettings_workout_detection);
+ workout.add(R.xml.devicesettings_workout_keep_screen_on);
+ workout.add(R.xml.devicesettings_workout_detection);
//
// Notifications
//
- settings.add(R.xml.devicesettings_header_notifications);
+ final List notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS);
if (supportsBluetoothPhoneCalls(device)) {
- settings.add(R.xml.devicesettings_phone_calls_watch_pair);
+ notifications.add(R.xml.devicesettings_phone_calls_watch_pair);
} else {
- settings.add(R.xml.devicesettings_display_caller);
+ notifications.add(R.xml.devicesettings_display_caller);
}
- settings.add(R.xml.devicesettings_sound_and_vibration);
- settings.add(R.xml.devicesettings_vibrationpatterns);
- settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
- settings.add(R.xml.devicesettings_send_app_notifications);
- settings.add(R.xml.devicesettings_screen_on_on_notifications);
- settings.add(R.xml.devicesettings_autoremove_notifications);
- settings.add(R.xml.devicesettings_canned_reply_16);
- settings.add(R.xml.devicesettings_transliteration);
+ notifications.add(R.xml.devicesettings_sound_and_vibration);
+ notifications.add(R.xml.devicesettings_vibrationpatterns);
+ notifications.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
+ notifications.add(R.xml.devicesettings_send_app_notifications);
+ notifications.add(R.xml.devicesettings_screen_on_on_notifications);
+ notifications.add(R.xml.devicesettings_autoremove_notifications);
+ notifications.add(R.xml.devicesettings_canned_reply_16);
+ notifications.add(R.xml.devicesettings_transliteration);
//
// Calendar
//
- settings.add(R.xml.devicesettings_header_calendar);
- settings.add(R.xml.devicesettings_sync_calendar);
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.CALENDAR,
+ R.xml.devicesettings_sync_calendar
+ );
//
// Other
//
- settings.add(R.xml.devicesettings_header_other);
if (getContactsSlotCount(device) > 0) {
- settings.add(R.xml.devicesettings_contacts);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_contacts);
}
- settings.add(R.xml.devicesettings_offline_voice);
- settings.add(R.xml.devicesettings_device_actions_without_not_wear);
- settings.add(R.xml.devicesettings_phone_silent_mode);
- settings.add(R.xml.devicesettings_buttonactions_upper_long);
- settings.add(R.xml.devicesettings_buttonactions_lower_short);
- settings.add(R.xml.devicesettings_weardirection);
- settings.add(R.xml.devicesettings_camera_remote);
- settings.add(R.xml.devicesettings_morning_updates);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_offline_voice);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_device_actions_without_not_wear);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_phone_silent_mode);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_buttonactions_upper_long);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_buttonactions_lower_short);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_weardirection);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_camera_remote);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_morning_updates);
//
// Connection
//
- settings.add(R.xml.devicesettings_header_connection);
- settings.add(R.xml.devicesettings_expose_hr_thirdparty);
- settings.add(R.xml.devicesettings_bt_connected_advertisement);
- settings.add(R.xml.devicesettings_high_mtu);
+ final List connection = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CONNECTION);
+ connection.add(R.xml.devicesettings_expose_hr_thirdparty);
+ connection.add(R.xml.devicesettings_bt_connected_advertisement);
+ connection.add(R.xml.devicesettings_high_mtu);
//
// Developer
//
- settings.add(R.xml.devicesettings_header_developer);
+ final List developer = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DEVELOPER);
if (ZeppOsLogsService.isSupported(getPrefs(device))) {
- settings.add(R.xml.devicesettings_app_logs_start_stop);
+ developer.add(R.xml.devicesettings_app_logs_start_stop);
}
if (supportsAlexa(device)) {
- settings.add(R.xml.devicesettings_huami2021_alexa);
+ developer.add(R.xml.devicesettings_huami2021_alexa);
}
if (supportsWifiHotspot(device)) {
- settings.add(R.xml.devicesettings_wifi_hotspot);
+ developer.add(R.xml.devicesettings_wifi_hotspot);
}
if (supportsFtpServer(device)) {
- settings.add(R.xml.devicesettings_ftp_server);
+ developer.add(R.xml.devicesettings_ftp_server);
}
- settings.add(R.xml.devicesettings_keep_activity_data_on_device);
- settings.add(R.xml.devicesettings_huami2021_fetch_operation_time_unit);
+ developer.add(R.xml.devicesettings_keep_activity_data_on_device);
+ developer.add(R.xml.devicesettings_huami2021_fetch_operation_time_unit);
- return ArrayUtils.toPrimitive(settings.toArray(new Integer[0]));
- }
-
- @Override
- public int[] getSupportedDeviceSpecificAuthenticationSettings() {
- return new int[]{
- R.xml.devicesettings_pairingkey
- };
+ return deviceSpecificSettings;
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
index 5a00e5fa4..48d7dcd79 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
@@ -269,6 +269,7 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
if (getFirmwareVersion() != null && getFirmwareVersion().smallerThan(new Version("2.20"))) {
supportedSettings = ArrayUtils.insert(1, supportedSettings, R.xml.devicesettings_fossilhybridhr_pre_fw220);
}
+ supportedSettings = ArrayUtils.add(supportedSettings, R.xml.devicesettings_custom_deviceicon);
return supportedSettings;
}
@@ -285,13 +286,6 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
};
}
- @Override
- public int[] getSupportedDeviceSpecificApplicationSettings() {
- return new int[]{
- R.xml.devicesettings_custom_deviceicon,
- };
- }
-
private boolean isHybridHR() {
List devices = GBApplication.app().getDeviceManager().getSelectedDevices();
for(GBDevice device : devices){
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
index 9d88b119e..72e31c488 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
@@ -464,13 +464,6 @@ public class TestDeviceCoordinator extends AbstractDeviceCoordinator {
return super.getSupportedDeviceSpecificConnectionSettings();
}
- @Override
- public int[] getSupportedDeviceSpecificApplicationSettings() {
- return new int[]{
- R.xml.devicesettings_custom_deviceicon,
- };
- }
-
@Override
public int[] getSupportedDeviceSpecificSettings(final GBDevice device) {
final List settings = new ArrayList<>();
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java
index bd0145e6e..d26e59b14 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java
@@ -38,6 +38,8 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@@ -370,117 +372,120 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
}
@Override
- public int[] getSupportedDeviceSpecificSettings(final GBDevice device) {
- final List settings = new ArrayList<>();
+ public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
+ final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
if (supports(device, FEAT_WEAR_MODE)) {
// TODO we should be able to get this from the band - right now it must be changed
// at least once from the band itself
- settings.add(R.xml.devicesettings_wearmode);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_wearmode);
}
//
// Time
//
- settings.add(R.xml.devicesettings_header_time);
- settings.add(R.xml.devicesettings_timeformat);
+ final List dateTime = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DATE_TIME);
+ dateTime.add(R.xml.devicesettings_timeformat);
if (getWorldClocksSlotCount() > 0) {
- settings.add(R.xml.devicesettings_world_clocks);
+ dateTime.add(R.xml.devicesettings_world_clocks);
}
//
// Display
//
- settings.add(R.xml.devicesettings_header_display);
+ final List display = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY);
if (supports(device, FEAT_DISPLAY_ITEMS)) {
- settings.add(R.xml.devicesettings_xiaomi_displayitems);
+ display.add(R.xml.devicesettings_xiaomi_displayitems);
}
if (this.supportsWidgets(device)) {
- settings.add(R.xml.devicesettings_widgets);
+ display.add(R.xml.devicesettings_widgets);
}
if (supports(device, FEAT_PASSWORD)) {
- settings.add(R.xml.devicesettings_password);
+ display.add(R.xml.devicesettings_password);
}
//
// Health
//
- settings.add(R.xml.devicesettings_header_health);
if (supportsStressMeasurement() && supports(device, FEAT_STRESS) && supportsSpo2() && supports(device, FEAT_SPO2)) {
- settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
} else if (supportsStressMeasurement() && supports(device, FEAT_STRESS)) {
- settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress);
} else {
- settings.add(R.xml.devicesettings_heartrate_sleep_activity);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_activity);
}
if (supports(device, FEAT_INACTIVITY)) {
- settings.add(R.xml.devicesettings_inactivity_dnd_no_threshold);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_inactivity_dnd_no_threshold);
}
if (supports(device, FEAT_SLEEP_MODE_SCHEDULE)) {
- settings.add(R.xml.devicesettings_sleep_mode_schedule);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_sleep_mode_schedule);
}
if (supports(device, FEAT_GOAL_NOTIFICATION)) {
- settings.add(R.xml.devicesettings_goal_notification);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_notification);
}
if (supports(device, FEAT_GOAL_SECONDARY)) {
- settings.add(R.xml.devicesettings_goal_secondary);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_secondary);
}
if (supports(device, FEAT_VITALITY_SCORE)) {
- settings.add(R.xml.devicesettings_vitality_score);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_vitality_score);
}
//
// Workout
//
- settings.add(R.xml.devicesettings_header_workout);
- settings.add(R.xml.devicesettings_workout_start_on_phone);
- settings.add(R.xml.devicesettings_workout_send_gps_to_band);
+ final List workout = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT);
+ workout.add(R.xml.devicesettings_workout_start_on_phone);
+ workout.add(R.xml.devicesettings_workout_send_gps_to_band);
//
// Notifications
//
- settings.add(R.xml.devicesettings_header_notifications);
+ final List notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS);
// TODO not implemented settings.add(R.xml.devicesettings_vibrationpatterns);
// TODO not implemented settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
- settings.add(R.xml.devicesettings_send_app_notifications);
+ notifications.add(R.xml.devicesettings_send_app_notifications);
if (supports(device, FEAT_SCREEN_ON_ON_NOTIFICATIONS)) {
- settings.add(R.xml.devicesettings_screen_on_on_notifications);
+ notifications.add(R.xml.devicesettings_screen_on_on_notifications);
}
- settings.add(R.xml.devicesettings_autoremove_notifications);
+ notifications.add(R.xml.devicesettings_autoremove_notifications);
if (getCannedRepliesSlotCount(device) > 0) {
- settings.add(R.xml.devicesettings_canned_dismisscall_16);
+ notifications.add(R.xml.devicesettings_canned_dismisscall_16);
}
//
// Calendar
//
if (supportsCalendarEvents()) {
- settings.add(R.xml.devicesettings_header_calendar);
- settings.add(R.xml.devicesettings_sync_calendar);
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.CALENDAR,
+ R.xml.devicesettings_header_calendar,
+ R.xml.devicesettings_sync_calendar
+ );
}
//
// Other
//
- settings.add(R.xml.devicesettings_header_other);
if (getContactsSlotCount(device) > 0) {
- settings.add(R.xml.devicesettings_contacts);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_contacts);
}
if (supports(device, FEAT_CAMERA_REMOTE)) {
- settings.add(R.xml.devicesettings_camera_remote);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_camera_remote);
}
if (supports(device, FEAT_DEVICE_ACTIONS)) {
- settings.add(R.xml.devicesettings_device_actions);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_device_actions);
}
- settings.add(R.xml.devicesettings_phone_silent_mode);
+ deviceSpecificSettings.addRootScreen(R.xml.devicesettings_phone_silent_mode);
//
// Developer
//
- settings.add(R.xml.devicesettings_header_developer);
- settings.add(R.xml.devicesettings_keep_activity_data_on_device);
+ deviceSpecificSettings.addRootScreen(
+ DeviceSpecificSettingsScreen.DEVELOPER,
+ R.xml.devicesettings_keep_activity_data_on_device
+ );
- return ArrayUtils.toPrimitive(settings.toArray(new Integer[0]));
+ return deviceSpecificSettings;
}
@Override
diff --git a/app/src/main/res/xml/devicesettings_root_activity_info.xml b/app/src/main/res/xml/devicesettings_root_activity_info.xml
new file mode 100644
index 000000000..fe5d7c307
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_activity_info.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_authentication.xml b/app/src/main/res/xml/devicesettings_root_authentication.xml
new file mode 100644
index 000000000..8e561282e
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_authentication.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_calendar.xml b/app/src/main/res/xml/devicesettings_root_calendar.xml
new file mode 100644
index 000000000..aaca622cd
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_calendar.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_connection.xml b/app/src/main/res/xml/devicesettings_root_connection.xml
new file mode 100644
index 000000000..a5880830f
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_connection.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_date_time.xml b/app/src/main/res/xml/devicesettings_root_date_time.xml
new file mode 100644
index 000000000..7a9f53258
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_date_time.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_developer.xml b/app/src/main/res/xml/devicesettings_root_developer.xml
new file mode 100644
index 000000000..307e157bf
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_developer.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_display.xml b/app/src/main/res/xml/devicesettings_root_display.xml
new file mode 100644
index 000000000..0246a6c87
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_display.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_notifications.xml b/app/src/main/res/xml/devicesettings_root_notifications.xml
new file mode 100644
index 000000000..e68a77eca
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_notifications.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/src/main/res/xml/devicesettings_root_workout.xml b/app/src/main/res/xml/devicesettings_root_workout.xml
new file mode 100644
index 000000000..457c2404a
--- /dev/null
+++ b/app/src/main/res/xml/devicesettings_root_workout.xml
@@ -0,0 +1,9 @@
+
+
+
+
+