mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 03:37:03 +01:00
Zepp OS 4: Fix shortcuts
This commit is contained in:
parent
8577c5d546
commit
aa9071e34e
@ -109,6 +109,7 @@ public class ZeppOsMenuType {
|
|||||||
put("00000029", "body_composition");
|
put("00000029", "body_composition");
|
||||||
put("0000002A", "readiness");
|
put("0000002A", "readiness");
|
||||||
put("0000002B", "zepp_pay");
|
put("0000002B", "zepp_pay");
|
||||||
|
put("000FFD39", "hrv");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public static final Map<String, String> controlCenterNameLookup = new HashMap<String, String>() {{
|
public static final Map<String, String> controlCenterNameLookup = new HashMap<String, String>() {{
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ArrayUtils.subarray;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -27,9 +29,12 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
|
||||||
@ -88,33 +93,33 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onSendConfiguration(final String config, final Prefs prefs) {
|
public boolean onSendConfiguration(final String config, final Prefs prefs) {
|
||||||
|
final byte menuType;
|
||||||
|
|
||||||
switch (config) {
|
switch (config) {
|
||||||
case HuamiConst.PREF_DISPLAY_ITEMS:
|
case HuamiConst.PREF_DISPLAY_ITEMS:
|
||||||
case HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE:
|
case HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE:
|
||||||
setDisplayItems(
|
menuType = DISPLAY_ITEMS_MENU;
|
||||||
DISPLAY_ITEMS_MENU,
|
break;
|
||||||
new ArrayList<>(prefs.getList(DeviceSettingsUtils.getPrefPossibleValuesKey(HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE), Collections.emptyList())),
|
|
||||||
new ArrayList<>(prefs.getList(HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE, Collections.emptyList()))
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
case HuamiConst.PREF_SHORTCUTS:
|
case HuamiConst.PREF_SHORTCUTS:
|
||||||
case HuamiConst.PREF_SHORTCUTS_SORTABLE:
|
case HuamiConst.PREF_SHORTCUTS_SORTABLE:
|
||||||
setDisplayItems(
|
menuType = DISPLAY_ITEMS_SHORTCUTS;
|
||||||
DISPLAY_ITEMS_SHORTCUTS,
|
break;
|
||||||
new ArrayList<>(prefs.getList(DeviceSettingsUtils.getPrefPossibleValuesKey(HuamiConst.PREF_SHORTCUTS_SORTABLE), Collections.emptyList())),
|
|
||||||
new ArrayList<>(prefs.getList(HuamiConst.PREF_SHORTCUTS_SORTABLE, Collections.emptyList()))
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
case HuamiConst.PREF_CONTROL_CENTER_SORTABLE:
|
case HuamiConst.PREF_CONTROL_CENTER_SORTABLE:
|
||||||
setDisplayItems(
|
menuType = DISPLAY_ITEMS_CONTROL_CENTER;
|
||||||
DISPLAY_ITEMS_CONTROL_CENTER,
|
break;
|
||||||
new ArrayList<>(prefs.getList(DeviceSettingsUtils.getPrefPossibleValuesKey(HuamiConst.PREF_CONTROL_CENTER_SORTABLE), Collections.emptyList())),
|
default:
|
||||||
new ArrayList<>(prefs.getList(HuamiConst.PREF_CONTROL_CENTER_SORTABLE, Collections.emptyList()))
|
return false;
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
setDisplayItems(
|
||||||
|
menuType,
|
||||||
|
new ArrayList<>(prefs.getList(DeviceSettingsUtils.getPrefPossibleValuesKey(config), Collections.emptyList())),
|
||||||
|
new ArrayList<>(prefs.getList(config, Collections.emptyList())),
|
||||||
|
FlagsMap.fromPrefValue(prefs.getString(config + "_flags", "{}"))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -132,43 +137,39 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
write(builder, new byte[]{CMD_REQUEST, type});
|
write(builder, new byte[]{CMD_REQUEST, type});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decodeAndUpdateDisplayItems(final byte[] payload) {
|
private void decodeAndUpdateDisplayItems(final byte[] payloadd) {
|
||||||
LOG.info("Got display items from band, type={}", payload[1]);
|
final ByteBuffer buf = ByteBuffer.wrap(payloadd).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.get(); // discard the command byte
|
||||||
|
|
||||||
final int numberScreens = payload[2];
|
final int type = buf.get();
|
||||||
final int expectedLength = 4 + numberScreens * 12;
|
final int numberScreens = buf.getShort();
|
||||||
if (payload.length != 4 + numberScreens * 12) {
|
|
||||||
LOG.error("Unexpected display items payload length {}, expected {}", payload.length, expectedLength);
|
LOG.info("Got {} display items of type {}", numberScreens, type);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String prefKey;
|
final String prefKey;
|
||||||
final Map<String, String> idMap;
|
final Map<String, String> idMap;
|
||||||
switch (payload[1]) {
|
switch (type) {
|
||||||
case DISPLAY_ITEMS_MENU:
|
case DISPLAY_ITEMS_MENU:
|
||||||
LOG.info("Got {} display items", numberScreens);
|
|
||||||
prefKey = HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE;
|
prefKey = HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE;
|
||||||
idMap = ZeppOsMenuType.displayItemNameLookup;
|
idMap = ZeppOsMenuType.displayItemNameLookup;
|
||||||
break;
|
break;
|
||||||
case DISPLAY_ITEMS_SHORTCUTS:
|
case DISPLAY_ITEMS_SHORTCUTS:
|
||||||
LOG.info("Got {} shortcuts", numberScreens);
|
|
||||||
prefKey = HuamiConst.PREF_SHORTCUTS_SORTABLE;
|
prefKey = HuamiConst.PREF_SHORTCUTS_SORTABLE;
|
||||||
idMap = ZeppOsMenuType.shortcutsNameLookup;
|
idMap = ZeppOsMenuType.shortcutsNameLookup;
|
||||||
break;
|
break;
|
||||||
case DISPLAY_ITEMS_CONTROL_CENTER:
|
case DISPLAY_ITEMS_CONTROL_CENTER:
|
||||||
LOG.info("Got {} control center", numberScreens);
|
|
||||||
prefKey = HuamiConst.PREF_CONTROL_CENTER_SORTABLE;
|
prefKey = HuamiConst.PREF_CONTROL_CENTER_SORTABLE;
|
||||||
idMap = ZeppOsMenuType.controlCenterNameLookup;
|
idMap = ZeppOsMenuType.controlCenterNameLookup;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG.error("Unknown display items type {}", String.format("0x%x", payload[1]));
|
LOG.error("Unknown display items type {}", String.format("0x%x", type));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String allScreensPrefKey = DeviceSettingsUtils.getPrefPossibleValuesKey(prefKey);
|
final String allScreensPrefKey = DeviceSettingsUtils.getPrefPossibleValuesKey(prefKey);
|
||||||
|
|
||||||
final boolean menuHasMoreSection;
|
final boolean menuHasMoreSection;
|
||||||
|
|
||||||
if (payload[1] == DISPLAY_ITEMS_MENU) {
|
if (type == DISPLAY_ITEMS_MENU) {
|
||||||
menuHasMoreSection = getCoordinator().mainMenuHasMoreSection();
|
menuHasMoreSection = getCoordinator().mainMenuHasMoreSection();
|
||||||
} else {
|
} else {
|
||||||
menuHasMoreSection = false;
|
menuHasMoreSection = false;
|
||||||
@ -177,6 +178,10 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
final String[] mainScreensArr = new String[numberScreens];
|
final String[] mainScreensArr = new String[numberScreens];
|
||||||
final String[] moreScreensArr = new String[numberScreens];
|
final String[] moreScreensArr = new String[numberScreens];
|
||||||
final List<String> allScreens = new LinkedList<>();
|
final List<String> allScreens = new LinkedList<>();
|
||||||
|
|
||||||
|
// we need to save the flags so that we can send them when setting the screens
|
||||||
|
final FlagsMap flagsMap = new FlagsMap();
|
||||||
|
|
||||||
if (menuHasMoreSection) {
|
if (menuHasMoreSection) {
|
||||||
// The band doesn't report the "more" screen, so we add it
|
// The band doesn't report the "more" screen, so we add it
|
||||||
allScreens.add("more");
|
allScreens.add("more");
|
||||||
@ -184,12 +189,32 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
|
|
||||||
for (int i = 0; i < numberScreens; i++) {
|
for (int i = 0; i < numberScreens; i++) {
|
||||||
// Screen IDs are sent as literal hex strings
|
// Screen IDs are sent as literal hex strings
|
||||||
final String screenId = new String(subarray(payload, 4 + i * 12, 4 + i * 12 + 8));
|
final String screenId = StringUtils.untilNullTerminator(buf);
|
||||||
final String screenNameOrId = idMap.containsKey(screenId) ? idMap.get(screenId) : screenId;
|
final String screenNameOrId = idMap.containsKey(screenId) ? idMap.get(screenId) : screenId;
|
||||||
allScreens.add(screenNameOrId);
|
allScreens.add(screenNameOrId);
|
||||||
|
|
||||||
final int screenSectionVal = payload[4 + i * 12 + 9];
|
final int screenSectionVal = buf.get();
|
||||||
final int screenPosition = payload[4 + i * 12 + 10];
|
final int screenPosition = buf.get();
|
||||||
|
final int flags = buf.get();
|
||||||
|
if (flags != 0) {
|
||||||
|
final Flags flagsObj = new Flags();
|
||||||
|
|
||||||
|
flagsObj.value = flags;
|
||||||
|
|
||||||
|
// 1 = settings / can't be removed
|
||||||
|
|
||||||
|
if ((flags & 2) != 0 || (flags & 4) != 0) {
|
||||||
|
// unsure which flag indicates the version and which indicates the unknown string
|
||||||
|
flagsObj.version = StringUtils.untilNullTerminator(buf);
|
||||||
|
|
||||||
|
if ((flags & 2) != 0 && (flags & 4) != 0) {
|
||||||
|
// but if both are set, we have a 2nd string
|
||||||
|
flagsObj.unk = StringUtils.untilNullTerminator(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flagsMap.put(screenId, flagsObj);
|
||||||
|
}
|
||||||
|
|
||||||
if (screenPosition >= numberScreens) {
|
if (screenPosition >= numberScreens) {
|
||||||
LOG.warn("Invalid screen position {}, ignoring", screenPosition);
|
LOG.warn("Invalid screen position {}, ignoring", screenPosition);
|
||||||
@ -230,6 +255,7 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
final String allScreensPrefValue = StringUtils.join(",", allScreens.toArray(new String[0])).toString();
|
final String allScreensPrefValue = StringUtils.join(",", allScreens.toArray(new String[0])).toString();
|
||||||
final String prefValue = StringUtils.join(",", screens.toArray(new String[0])).toString();
|
final String prefValue = StringUtils.join(",", screens.toArray(new String[0])).toString();
|
||||||
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences()
|
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences()
|
||||||
|
.withPreference(prefKey + "_flags", flagsMap.toPrefValue())
|
||||||
.withPreference(allScreensPrefKey, allScreensPrefValue)
|
.withPreference(allScreensPrefKey, allScreensPrefValue)
|
||||||
.withPreference(prefKey, prefValue);
|
.withPreference(prefKey, prefValue);
|
||||||
|
|
||||||
@ -238,10 +264,11 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
|
|
||||||
private void setDisplayItems(final byte menuType,
|
private void setDisplayItems(final byte menuType,
|
||||||
final List<String> allSettings,
|
final List<String> allSettings,
|
||||||
List<String> enabledList) {
|
List<String> enabledList,
|
||||||
|
final FlagsMap flags) {
|
||||||
try {
|
try {
|
||||||
final TransactionBuilder builder = new TransactionBuilder("set display items type " + menuType);
|
final TransactionBuilder builder = new TransactionBuilder("set display items type " + menuType);
|
||||||
setDisplayItems(builder, menuType, allSettings, enabledList);
|
setDisplayItems(builder, menuType, allSettings, enabledList, flags);
|
||||||
builder.queue(getSupport().getQueue());
|
builder.queue(getSupport().getQueue());
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
LOG.error("Failed to set display items", e);
|
LOG.error("Failed to set display items", e);
|
||||||
@ -251,7 +278,8 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
private void setDisplayItems(final TransactionBuilder builder,
|
private void setDisplayItems(final TransactionBuilder builder,
|
||||||
final byte menuType,
|
final byte menuType,
|
||||||
final List<String> allSettings,
|
final List<String> allSettings,
|
||||||
List<String> enabledList) {
|
List<String> enabledList,
|
||||||
|
final FlagsMap flagsMap) {
|
||||||
final boolean isMainMenu = menuType == DISPLAY_ITEMS_MENU;
|
final boolean isMainMenu = menuType == DISPLAY_ITEMS_MENU;
|
||||||
final boolean isShortcuts = menuType == DISPLAY_ITEMS_SHORTCUTS;
|
final boolean isShortcuts = menuType == DISPLAY_ITEMS_SHORTCUTS;
|
||||||
final boolean hasMoreSection;
|
final boolean hasMoreSection;
|
||||||
@ -283,6 +311,11 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flagsMap == null) {
|
||||||
|
LOG.error("Flags map is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMainMenu && !enabledList.contains("settings")) {
|
if (isMainMenu && !enabledList.contains("settings")) {
|
||||||
// Settings can't be disabled
|
// Settings can't be disabled
|
||||||
enabledList.add("settings");
|
enabledList.add("settings");
|
||||||
@ -302,13 +335,22 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
numItems--;
|
numItems--;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ByteBuffer buf = ByteBuffer.allocate(4 + numItems * 12);
|
int flagsOverhead = 0;
|
||||||
|
for (final Map.Entry<String, Flags> e : flagsMap.entrySet()) {
|
||||||
|
if (e.getValue().version != null) {
|
||||||
|
flagsOverhead += e.getValue().version.getBytes(StandardCharsets.UTF_8).length + 1;
|
||||||
|
}
|
||||||
|
if (e.getValue().unk != null) {
|
||||||
|
flagsOverhead += e.getValue().unk.getBytes(StandardCharsets.UTF_8).length + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ByteBuffer buf = ByteBuffer.allocate(4 + numItems * 12 + flagsOverhead);
|
||||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
buf.put(CMD_CREATE);
|
buf.put(CMD_CREATE);
|
||||||
buf.put(menuType);
|
buf.put(menuType);
|
||||||
buf.put((byte) numItems);
|
buf.putShort((short) numItems);
|
||||||
buf.put((byte) 0x00);
|
|
||||||
|
|
||||||
byte pos = 0;
|
byte pos = 0;
|
||||||
boolean inMoreSection = false;
|
boolean inMoreSection = false;
|
||||||
@ -323,7 +365,7 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String id = idMap.containsKey(name) ? idMap.get(name) : name;
|
final String id = idMap.containsKey(name) ? Objects.requireNonNull(idMap.get(name)) : name;
|
||||||
if (!ID_REGEX.matcher(id).find()) {
|
if (!ID_REGEX.matcher(id).find()) {
|
||||||
LOG.error("Screen item id '{}' is not 8-char hex string", id);
|
LOG.error("Screen item id '{}' is not 8-char hex string", id);
|
||||||
continue;
|
continue;
|
||||||
@ -343,7 +385,20 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
buf.put((byte) 0);
|
buf.put((byte) 0);
|
||||||
buf.put(sectionKey);
|
buf.put(sectionKey);
|
||||||
buf.put(pos++);
|
buf.put(pos++);
|
||||||
buf.put((byte) (id.equals("00000013") ? 1 : 0));
|
final Flags flags = flagsMap.get(id);
|
||||||
|
if (flags != null && flags.value != 0) {
|
||||||
|
buf.put((byte) (flags.value));
|
||||||
|
if (flags.version != null) {
|
||||||
|
buf.put(flags.version.getBytes(StandardCharsets.UTF_8));
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
|
if (flags.unk != null) {
|
||||||
|
buf.put(flags.unk.getBytes(StandardCharsets.UTF_8));
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set all disabled items
|
// Set all disabled items
|
||||||
@ -353,7 +408,7 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String id = idMap.containsKey(name) ? idMap.get(name) : name;
|
final String id = idMap.containsKey(name) ? Objects.requireNonNull(idMap.get(name)) : name;
|
||||||
if (!ID_REGEX.matcher(id).find()) {
|
if (!ID_REGEX.matcher(id).find()) {
|
||||||
LOG.error("Screen item id '{}' is not 8-char hex string", id);
|
LOG.error("Screen item id '{}' is not 8-char hex string", id);
|
||||||
continue;
|
continue;
|
||||||
@ -364,9 +419,92 @@ public class ZeppOsDisplayItemsService extends AbstractZeppOsService {
|
|||||||
buf.put((byte) 0);
|
buf.put((byte) 0);
|
||||||
buf.put(DISPLAY_ITEMS_SECTION_DISABLED);
|
buf.put(DISPLAY_ITEMS_SECTION_DISABLED);
|
||||||
buf.put(pos++);
|
buf.put(pos++);
|
||||||
buf.put((byte) (id.equals("00000013") ? 1 : 0));
|
final Flags flags = flagsMap.get(id);
|
||||||
|
if (flags != null && flags.value != 0) {
|
||||||
|
buf.put((byte) (flags.value));
|
||||||
|
if (flags.version != null) {
|
||||||
|
buf.put(flags.version.getBytes(StandardCharsets.UTF_8));
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
|
if (flags.unk != null) {
|
||||||
|
buf.put(flags.unk.getBytes(StandardCharsets.UTF_8));
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.put((byte) 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write(builder, buf.array());
|
write(builder, buf.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class Flags {
|
||||||
|
private int value = 0;
|
||||||
|
private String version = null;
|
||||||
|
private String unk = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When requesting the items from the watch, it sends a bitmask with flags, and a version / unknown
|
||||||
|
* string. We need to persist this so that we can send it back when setting the display items.
|
||||||
|
*/
|
||||||
|
private static class FlagsMap extends HashMap<String, Flags> {
|
||||||
|
@Nullable
|
||||||
|
private String toPrefValue() {
|
||||||
|
final JSONObject jsonObject = new JSONObject();
|
||||||
|
|
||||||
|
for (final Map.Entry<String, Flags> e : entrySet()) {
|
||||||
|
final JSONObject entryObj = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
entryObj.put("value", e.getValue().value);
|
||||||
|
if (e.getValue().version != null) {
|
||||||
|
entryObj.put("version", e.getValue().version);
|
||||||
|
}
|
||||||
|
if (e.getValue().unk != null) {
|
||||||
|
entryObj.put("unk", e.getValue().unk);
|
||||||
|
}
|
||||||
|
jsonObject.put(e.getKey(), entryObj);
|
||||||
|
} catch (final JSONException ex) {
|
||||||
|
LOG.error("This should never happen", ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonObject.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static FlagsMap fromPrefValue(final String value) {
|
||||||
|
final FlagsMap flagsMap = new FlagsMap();
|
||||||
|
|
||||||
|
final JSONObject flagsMapObj;
|
||||||
|
try {
|
||||||
|
flagsMapObj = new JSONObject(value);
|
||||||
|
|
||||||
|
final Iterator<String> keys = flagsMapObj.keys();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
final String id = keys.next();
|
||||||
|
final JSONObject flagsObj = flagsMapObj.getJSONObject(id);
|
||||||
|
|
||||||
|
final Flags flags = new Flags();
|
||||||
|
if (flagsObj.has("value")) {
|
||||||
|
flags.value = flagsObj.getInt("value");
|
||||||
|
}
|
||||||
|
if (flagsObj.has("version")) {
|
||||||
|
flags.version = flagsObj.getString("version");
|
||||||
|
}
|
||||||
|
if (flagsObj.has("unk")) {
|
||||||
|
flags.unk = flagsObj.getString("unk");
|
||||||
|
}
|
||||||
|
flagsMap.put(id, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flagsMap;
|
||||||
|
} catch (final JSONException ex) {
|
||||||
|
LOG.error("This should never happen", ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -887,6 +887,7 @@
|
|||||||
<item>@string/menuitem_thermometer</item>
|
<item>@string/menuitem_thermometer</item>
|
||||||
<item>@string/menuitem_workout_shortcuts</item>
|
<item>@string/menuitem_workout_shortcuts</item>
|
||||||
<item>@string/menuitem_apps_shortcuts</item>
|
<item>@string/menuitem_apps_shortcuts</item>
|
||||||
|
<item>@string/hrv</item>
|
||||||
<!-- dummy item -->
|
<!-- dummy item -->
|
||||||
<item>@string/menuitem_more</item>
|
<item>@string/menuitem_more</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
@ -941,6 +942,7 @@
|
|||||||
<item>thermometer</item>
|
<item>thermometer</item>
|
||||||
<item>workout_shortcuts</item>
|
<item>workout_shortcuts</item>
|
||||||
<item>apps_shortcuts</item>
|
<item>apps_shortcuts</item>
|
||||||
|
<item>hrv</item>
|
||||||
<!-- dummy item -->
|
<!-- dummy item -->
|
||||||
<item>more</item>
|
<item>more</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
Loading…
Reference in New Issue
Block a user