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 5b43b9e97..23bfed87a 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
@@ -17,6 +17,7 @@
package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;
@@ -27,7 +28,12 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SeekBarPreference;
+import androidx.preference.SwitchPreference;
import com.mobeta.android.dslv.DragSortListPreference;
import com.mobeta.android.dslv.DragSortListPreferenceFragment;
@@ -204,6 +210,8 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
static final String FRAGMENT_TAG = "DEVICE_SPECIFIC_SETTINGS_FRAGMENT";
+ private final SharedPreferencesChangeHandler sharedPreferencesChangeHandler = new SharedPreferencesChangeHandler();
+
private void setSettingsFileSuffix(String settingsFileSuffix, @NonNull int[] supportedSettings, String[] supportedLanguages) {
Bundle args = new Bundle();
args.putString("settingsFileSuffix", settingsFileSuffix);
@@ -267,6 +275,24 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
setChangeListener();
}
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ final SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences();
+
+ reloadPreferences(sharedPreferences, getPreferenceScreen());
+
+ sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferencesChangeHandler);
+ }
+
+ @Override
+ public void onStop() {
+ getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(sharedPreferencesChangeHandler);
+
+ super.onStop();
+ }
+
/*
* delayed execution so that the preferences are applied first
*/
@@ -906,4 +932,59 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
});
}
}
+
+ /**
+ * Reload the preferences in the current screen. This is needed when the user enters or exists a PreferenceScreen,
+ * otherwise the settings won't be reloaded by the {@link SharedPreferencesChangeHandler}, as the preferences return
+ * null, since they're not visible.
+ *
+ * @param sharedPreferences the {@link SharedPreferences} instance
+ * @param preferenceGroup the {@link PreferenceGroup} for which preferences will be reloaded
+ */
+ private void reloadPreferences(final SharedPreferences sharedPreferences, final PreferenceGroup preferenceGroup) {
+ for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) {
+ final Preference preference = preferenceGroup.getPreference(i);
+
+ LOG.debug("Reloading {}", preference.getKey());
+
+ if (preference instanceof PreferenceCategory) {
+ reloadPreferences(sharedPreferences, (PreferenceCategory) preference);
+ continue;
+ }
+
+ sharedPreferencesChangeHandler.onSharedPreferenceChanged(sharedPreferences, preference.getKey());
+ }
+ }
+
+ /**
+ * Handler for preference changes, update UI accordingly (if device updates the preferences).
+ */
+ private class SharedPreferencesChangeHandler implements SharedPreferences.OnSharedPreferenceChangeListener {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ LOG.debug("Preference changed: {}", key);
+
+ final Preference preference = findPreference(key);
+ if (preference == null) {
+ LOG.warn("Preference {} not found, ignoring", key);
+
+ return;
+ }
+
+ if (preference instanceof SeekBarPreference) {
+ final SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
+ seekBarPreference.setValue(prefs.getInt(key, seekBarPreference.getValue()));
+ } else if (preference instanceof SwitchPreference) {
+ final SwitchPreference switchPreference = (SwitchPreference) preference;
+ switchPreference.setChecked(prefs.getBoolean(key, switchPreference.isChecked()));
+ } else if (preference instanceof ListPreference) {
+ final ListPreference listPreference = (ListPreference) preference;
+ listPreference.setValue(prefs.getString(key, listPreference.getValue()));
+ } else if (preference instanceof PreferenceScreen) {
+ // Ignoring
+ } else {
+ LOG.warn("Unknown preference class {}, ignoring", preference.getClass());
+ }
+ }
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceInfo.java
new file mode 100644
index 000000000..136f98704
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceInfo.java
@@ -0,0 +1,32 @@
+/* Copyright (C) 2021 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.deviceevents;
+
+import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
+import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
+
+public class GBDeviceEventUpdateDeviceInfo extends GBDeviceEvent {
+ public ItemWithDetails item;
+
+ public GBDeviceEventUpdateDeviceInfo(final ItemWithDetails item) {
+ this.item = item;
+ }
+
+ public GBDeviceEventUpdateDeviceInfo(final String name, final String details) {
+ this(new GenericItem(name, details));
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceState.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceState.java
new file mode 100644
index 000000000..dbe610deb
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdateDeviceState.java
@@ -0,0 +1,27 @@
+/* Copyright (C) 2021 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.deviceevents;
+
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class GBDeviceEventUpdateDeviceState extends GBDeviceEvent {
+ public GBDevice.State state;
+
+ public GBDeviceEventUpdateDeviceState(final GBDevice.State state) {
+ this.state = state;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdatePreferences.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdatePreferences.java
new file mode 100644
index 000000000..a467d06ad
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventUpdatePreferences.java
@@ -0,0 +1,90 @@
+/* Copyright (C) 2021 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.deviceevents;
+
+import android.content.SharedPreferences;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class GBDeviceEventUpdatePreferences extends GBDeviceEvent {
+ private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventUpdatePreferences.class);
+
+ public final Map preferences;
+
+ public GBDeviceEventUpdatePreferences() {
+ this.preferences = new HashMap<>();
+ }
+
+ public GBDeviceEventUpdatePreferences(final Map preferences) {
+ this.preferences = preferences;
+ }
+
+ public GBDeviceEventUpdatePreferences(final String key, final Object value) {
+ this.preferences = new HashMap<>();
+ this.preferences.put(key, value);
+ }
+
+ public GBDeviceEventUpdatePreferences withPreference(final String key, final Object value) {
+ this.preferences.put(key, value);
+
+ return this;
+ }
+
+ public GBDeviceEventUpdatePreferences withPreferences(final Map preferences) {
+ this.preferences.putAll(preferences);
+
+ return this;
+ }
+
+ /**
+ * Update a {@link SharedPreferences} instance with the preferences in the event.
+ *
+ * @param prefs the SharedPreferences object to update.
+ */
+ public void update(final SharedPreferences prefs) {
+ final SharedPreferences.Editor editor = prefs.edit();
+
+ for (String key : preferences.keySet()) {
+ final Object value = preferences.get(key);
+
+ LOG.debug("Updating {} = {}", key, value);
+
+ if (value instanceof Integer) {
+ editor.putInt(key, (Integer) value);
+ } else if (value instanceof Boolean) {
+ editor.putBoolean(key, (Boolean) value);
+ } else if (value instanceof String) {
+ editor.putString(key, (String) value);
+ } else if (value instanceof Float) {
+ editor.putFloat(key, (Float) value);
+ } else if (value instanceof Long) {
+ editor.putLong(key, (Long) value);
+ } else if (value instanceof Set) {
+ editor.putStringSet(key, (Set) value);
+ } else {
+ LOG.warn("Unknown preference value type {} for {}", value.getClass(), key);
+ }
+ }
+
+ editor.apply();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
index e5cc1b6ee..0848c1117 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
@@ -61,9 +61,12 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallContro
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventLEDColor;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceState;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.entities.BatteryLevel;
@@ -172,6 +175,12 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
handleGBDeviceEvent((GBDeviceEventFindPhone) deviceEvent);
} else if (deviceEvent instanceof GBDeviceEventLEDColor) {
handleGBDeviceEvent((GBDeviceEventLEDColor) deviceEvent);
+ } else if (deviceEvent instanceof GBDeviceEventUpdateDeviceInfo) {
+ handleGBDeviceEvent((GBDeviceEventUpdateDeviceInfo) deviceEvent);
+ } else if (deviceEvent instanceof GBDeviceEventUpdatePreferences) {
+ handleGBDeviceEvent((GBDeviceEventUpdatePreferences) deviceEvent);
+ } else if (deviceEvent instanceof GBDeviceEventUpdateDeviceState) {
+ handleGBDeviceEvent((GBDeviceEventUpdateDeviceState) deviceEvent);
} else if (deviceEvent instanceof GBDeviceEventFmFrequency) {
handleGBDeviceEvent((GBDeviceEventFmFrequency) deviceEvent);
}
@@ -279,6 +288,32 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
gbDevice.sendDeviceUpdateIntent(context);
}
+ protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceInfo itemEvent) {
+ if (gbDevice == null) {
+ return;
+ }
+
+ gbDevice.addDeviceInfo(itemEvent.item);
+ gbDevice.sendDeviceUpdateIntent(context);
+ }
+
+ protected void handleGBDeviceEvent(GBDeviceEventUpdatePreferences savePreferencesEvent) {
+ if (gbDevice == null) {
+ return;
+ }
+
+ savePreferencesEvent.update(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()));
+ }
+
+ protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceState updateDeviceState) {
+ if (gbDevice == null) {
+ return;
+ }
+
+ gbDevice.setState(updateDeviceState.state);
+ gbDevice.sendDeviceUpdateIntent(getContext());
+ }
+
protected void handleGBDeviceEvent(GBDeviceEventFmFrequency frequencyEvent) {
Context context = getContext();
LOG.info("Got event for FM Frequency");