mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Merge pull request 'add BundleUtils.addToBundle' (#6284)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/6284
This commit is contained in:
+2
-21
@@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.BundleUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.backup.PeriodicZipExporter;
|
||||
@@ -328,27 +329,7 @@ public class IntentApiReceiver extends BroadcastReceiver {
|
||||
}
|
||||
String option = key.substring(prefix.length());
|
||||
Object extra = extras.get(key);
|
||||
if (extra == null) {
|
||||
options.putSerializable(option, null);
|
||||
} else if (extra instanceof String value) {
|
||||
options.putString(option, value);
|
||||
} else if (extra instanceof Boolean value) {
|
||||
options.putBoolean(option, value);
|
||||
} else if (extra instanceof Integer value) {
|
||||
options.putInt(option, value);
|
||||
} else if (extra instanceof Long value) {
|
||||
options.putLong(option, value);
|
||||
} else if (extra instanceof Float value) {
|
||||
options.putFloat(option, value);
|
||||
} else if (extra instanceof float[] value) {
|
||||
options.putFloatArray(option, value);
|
||||
} else if (extra instanceof int[] value) {
|
||||
options.putIntArray(option, value);
|
||||
} else if (extra instanceof long[] value) {
|
||||
options.putLongArray(option, value);
|
||||
} else if (extra instanceof Parcelable value) {
|
||||
options.putParcelable(option, value);
|
||||
} else {
|
||||
if (!BundleUtils.addToBundle(options, key, extra)) {
|
||||
LOG.warn("unhandled extra {} {} {}", option, extra, extra.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
+4
-9
@@ -141,6 +141,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLESingleDevic
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.BundleUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.EmojiConverter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@@ -1053,22 +1054,16 @@ public class BangleJSDeviceSupport extends AbstractBTLESingleDeviceSupport {
|
||||
if (json.has("extra")) {
|
||||
JSONObject extra = json.getJSONObject("extra");
|
||||
Iterator<String> iter = extra.keys();
|
||||
Bundle extras = new Bundle();
|
||||
while (iter.hasNext()) {
|
||||
String key = iter.next();
|
||||
Object value = extra.get(key);
|
||||
|
||||
if (value instanceof Boolean boolExtra) {
|
||||
in.putExtra(key, boolExtra);
|
||||
} else if (value instanceof Integer integerExtra) {
|
||||
in.putExtra(key, integerExtra);
|
||||
} else if (value instanceof Long longExtra) {
|
||||
in.putExtra(key, longExtra);
|
||||
} else if (value instanceof Double doubleExtra) {
|
||||
in.putExtra(key, doubleExtra);
|
||||
} else {
|
||||
if (!BundleUtils.addToBundle(extras, key, value)) {
|
||||
in.putExtra(key, value.toString());
|
||||
}
|
||||
}
|
||||
in.putExtras(extras);
|
||||
}
|
||||
LOG.info("Executing intent:\n\t" + String.valueOf(in) + "\n\tTargeting: " + target);
|
||||
//GB.toast(getContext(), String.valueOf(in), Toast.LENGTH_LONG, GB.INFO);
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/* Copyright (C) 2026 Thomas Kuehne
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Size;
|
||||
import android.util.SizeF;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public final class BundleUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BundleUtils.class);
|
||||
|
||||
private BundleUtils() {
|
||||
throw new UnsupportedOperationException("static utility class");
|
||||
}
|
||||
|
||||
/// Put the {@code value} into the {@code bundle}. Supports simple {@link JSONObject} as well as
|
||||
/// non-empty {@link JSONArray} that contain exclusively one of {@link Boolean}, {@link Double},
|
||||
/// {@link Integer}, {@link Long}, or {@link String}.
|
||||
///
|
||||
/// @return {@code true} if the {@code value} was actually put into the {@code bundle}
|
||||
public static boolean addToBundle(@NonNull final Bundle bundle,
|
||||
@NonNull final String key,
|
||||
@Nullable final Object value) {
|
||||
if (value == null || JSONObject.NULL.equals(value)) {
|
||||
bundle.putString(key, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Boolean extra) {
|
||||
bundle.putBoolean(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final boolean[] extra) {
|
||||
bundle.putBooleanArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Byte extra) {
|
||||
bundle.putByte(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final byte[] extra) {
|
||||
bundle.putByteArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Short extra) {
|
||||
bundle.putShort(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final short[] extra) {
|
||||
bundle.putShortArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Character extra) {
|
||||
bundle.putChar(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final char[] extra) {
|
||||
bundle.putCharArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Integer extra) {
|
||||
bundle.putInt(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final int[] extra) {
|
||||
bundle.putIntArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Long extra) {
|
||||
bundle.putLong(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final long[] extra) {
|
||||
bundle.putLongArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Float extra) {
|
||||
bundle.putFloat(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final float[] extra) {
|
||||
bundle.putFloatArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Double extra) {
|
||||
bundle.putDouble(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final double[] extra) {
|
||||
bundle.putDoubleArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final String extra) {
|
||||
bundle.putString(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final String[] extra) {
|
||||
bundle.putStringArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final CharSequence extra) {
|
||||
bundle.putCharSequence(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final CharSequence[] extra) {
|
||||
bundle.putCharSequenceArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Bundle extra) {
|
||||
bundle.putBundle(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final SizeF extra) {
|
||||
bundle.putSizeF(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final IBinder extra) {
|
||||
bundle.putBinder(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Parcelable extra) {
|
||||
bundle.putParcelable(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Parcelable[] extra) {
|
||||
bundle.putParcelableArray(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Serializable extra) {
|
||||
bundle.putSerializable(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final Size extra) {
|
||||
bundle.putSize(key, extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value instanceof final JSONArray jsonArray) {
|
||||
try {
|
||||
if (jsonArray.length() < 1) {
|
||||
LOG.warn("empty array '{}' is unsupported", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
Object first = jsonArray.get(0);
|
||||
if (first instanceof Boolean) {
|
||||
boolean[] array = new boolean[jsonArray.length()];
|
||||
for (int arrayIndex = 0; arrayIndex < jsonArray.length(); arrayIndex++) {
|
||||
Object element = jsonArray.get(arrayIndex);
|
||||
if (element instanceof final Boolean x) {
|
||||
array[arrayIndex] = x;
|
||||
} else {
|
||||
LOG.warn("boolean array '{}' contains unsupported value '{}' at index {}",
|
||||
key, element, arrayIndex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bundle.putBooleanArray(key, array);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (first instanceof Double) {
|
||||
double[] array = new double[jsonArray.length()];
|
||||
for (int arrayIndex = 0; arrayIndex < jsonArray.length(); arrayIndex++) {
|
||||
Object element = jsonArray.get(arrayIndex);
|
||||
if (element instanceof final Double x) {
|
||||
array[arrayIndex] = x;
|
||||
} else {
|
||||
LOG.warn("double array '{}' contains unsupported value '{}' at index {}",
|
||||
key, element, arrayIndex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bundle.putDoubleArray(key, array);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (first instanceof Integer || first instanceof Long) {
|
||||
long[] array = new long[jsonArray.length()];
|
||||
for (int arrayIndex = 0; arrayIndex < jsonArray.length(); arrayIndex++) {
|
||||
Object element = jsonArray.get(arrayIndex);
|
||||
if (element instanceof final Long x) {
|
||||
array[arrayIndex] = x;
|
||||
} else if (element instanceof final Integer x) {
|
||||
array[arrayIndex] = x.longValue();
|
||||
} else {
|
||||
LOG.warn("long array '{}' contains unsupported value '{}' at index {}",
|
||||
key, element, arrayIndex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bundle.putLongArray(key, array);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (first instanceof String) {
|
||||
String[] array = new String[jsonArray.length()];
|
||||
for (int arrayIndex = 0; arrayIndex < jsonArray.length(); arrayIndex++) {
|
||||
Object element = jsonArray.get(arrayIndex);
|
||||
if (element instanceof final String x) {
|
||||
array[arrayIndex] = x;
|
||||
} else if (element == null) {
|
||||
array[arrayIndex] = null;
|
||||
} else {
|
||||
LOG.warn("String array '{}' contains unsupported value '{}' at index {}",
|
||||
key, element, arrayIndex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bundle.putStringArray(key, array);
|
||||
return true;
|
||||
}
|
||||
} catch (final JSONException exception) {
|
||||
LOG.warn("failed to add JSONArray: {}", exception.getLocalizedMessage(), exception);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.warn("failed to add {}: {}", value.getClass(), value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/* Copyright (C) 2026 Thomas Kuehne
|
||||
|
||||
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 <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.BundleUtils.addToBundle;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Size;
|
||||
import android.util.SizeF;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.TestBase;
|
||||
|
||||
public class BundleUtilsTest extends TestBase {
|
||||
@Test
|
||||
public void testCommonTypes() {
|
||||
Object[] values = {
|
||||
null,
|
||||
true,
|
||||
new boolean[]{true, false},
|
||||
(byte) 12,
|
||||
new byte[]{12, 23},
|
||||
(short) 1234,
|
||||
new short[]{1234, 2345},
|
||||
(char) 1234,
|
||||
new char[]{1234, 2345},
|
||||
123456,
|
||||
new int[]{123456},
|
||||
123456789L,
|
||||
new long[]{123456789L},
|
||||
1.1f,
|
||||
new float[]{1.1f, 1.2f},
|
||||
2.1,
|
||||
new double[]{2.1, 2.2},
|
||||
"abc",
|
||||
new String[]{"abc"},
|
||||
Uri.parse("http://example.com"),
|
||||
new Parcelable[]{Uri.parse("http://example.com")},
|
||||
CharBuffer.wrap("abc"),
|
||||
new CharBuffer[]{CharBuffer.wrap("abc")},
|
||||
new Serializable() {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 8578229259758102775L;
|
||||
},
|
||||
new Bundle(),
|
||||
new SizeF(1.2f, 3.4f),
|
||||
new Size(1, 3),
|
||||
};
|
||||
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = values[i];
|
||||
assertTrue("add[" + i + "] " + value, addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
assertEquals("check[" + i + "]", value, actual);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
assertFalse(addToBundle(bundle, "object", new Object()));
|
||||
assertEquals(0, bundle.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJson() throws JSONException {
|
||||
JSONObject[] objects = {
|
||||
new JSONObject().put("key", true),
|
||||
new JSONObject().put("key", false),
|
||||
new JSONObject().put("key", Integer.MAX_VALUE),
|
||||
new JSONObject().put("key", Long.MAX_VALUE),
|
||||
new JSONObject().put("key", 1.2),
|
||||
new JSONObject().put("key", "xyz"),
|
||||
new JSONObject("{\"key\": null }"),
|
||||
};
|
||||
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
Bundle bundle = new Bundle();
|
||||
JSONObject object = objects[i];
|
||||
Object value = object.get("key");
|
||||
assertTrue("add[" + i + "]: " + object, addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
if(value == JSONObject.NULL){
|
||||
value = null;
|
||||
}
|
||||
assertEquals("check[" + i + "]: " + object, value, actual);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = new JSONObject("{ \"key\" : [false, true] }").get("key");
|
||||
assertTrue(addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
assertArrayEquals(new boolean[]{false, true}, (boolean[]) actual);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = new JSONObject("{ \"key\" : [123, 9223372036854775807] }").get("key");
|
||||
assertTrue(addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
assertArrayEquals(new long[]{123L, 9223372036854775807L}, (long[]) actual);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = new JSONObject("{ \"key\" : [1.2, 3.4] }").get("key");
|
||||
assertTrue(addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
assertArrayEquals(new double[]{1.2, 3.4}, (double[]) actual, 0.001);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = new JSONObject("{ \"key\" : [\"123\", \"abc\"] }").get("key");
|
||||
assertTrue(addToBundle(bundle, "key", value));
|
||||
Object actual = bundle.get("key");
|
||||
assertArrayEquals(new String[]{"123", "abc"}, (String[]) actual);
|
||||
assertEquals(1, bundle.size());
|
||||
}
|
||||
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
Object value = new JSONObject("{ \"key\" : [] }").get("key");
|
||||
assertFalse(addToBundle(bundle, "key", value));
|
||||
assertEquals(0, bundle.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user