mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Anker: Add new device Soundcore Sport X20 (#5987)
This is an almost full implementation for [Anker](https://gadgetbridge.org/gadgets/headphones/anker/) [Soundcore Sport X20](https://www.soundcore.com/products/a3968-sport-x20-earbuds) earbuds. Provides: - Firmware version and serial number - Display battery life when sent by earbuds - ANC Settings - Find Device - Equalizer with Presets - 3D Surrounding Sound - Toggle "Touch Tone" (sound when button is pressed) - Set the behavior of button actions - Set Auto Power-Off Timer - Enable discovery/pairing to add a second device to use the earbuds Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/5987
This commit is contained in:
+2
@@ -520,6 +520,8 @@ public class DeviceSettingsPreferenceConst {
|
|||||||
public static final String PREF_SOUNDCORE_VOICE_PROMPTS = "pref_soundcore_voice_prompts";
|
public static final String PREF_SOUNDCORE_VOICE_PROMPTS = "pref_soundcore_voice_prompts";
|
||||||
public static final String PREF_SOUNDCORE_BUTTON_BRIGHTNESS = "pref_soundcore_button_brightness";
|
public static final String PREF_SOUNDCORE_BUTTON_BRIGHTNESS = "pref_soundcore_button_brightness";
|
||||||
public static final String PREF_SOUNDCORE_AUTO_POWER_OFF = "pref_soundcore_auto_power_off";
|
public static final String PREF_SOUNDCORE_AUTO_POWER_OFF = "pref_soundcore_auto_power_off";
|
||||||
|
public static final String PREF_SOUNDCORE_3D_SURROUND = "pref_soundcore_3d_surround";
|
||||||
|
public static final String PREF_SOUNDCORE_ENABLE_PAIRING_MODE = "pref_soundcore_enable_pairing_mode";
|
||||||
public static final String PREF_SOUNDCORE_LDAC_MODE = "pref_soundcore_ldac_mode";
|
public static final String PREF_SOUNDCORE_LDAC_MODE = "pref_soundcore_ldac_mode";
|
||||||
public static final String PREF_SOUNDCORE_GAMING_MODE = "pref_soundcore_gaming_mode";
|
public static final String PREF_SOUNDCORE_GAMING_MODE = "pref_soundcore_gaming_mode";
|
||||||
public static final String PREF_SOUNDCORE_ADAPTIVE_DIRECTION = "pref_soundcore_adaptive_direction";
|
public static final String PREF_SOUNDCORE_ADAPTIVE_DIRECTION = "pref_soundcore_adaptive_direction";
|
||||||
|
|||||||
+1
@@ -910,6 +910,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
|
|||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_VOICE_PROMPTS);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_VOICE_PROMPTS);
|
||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_BUTTON_BRIGHTNESS);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_BUTTON_BRIGHTNESS);
|
||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_AUTO_POWER_OFF);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_AUTO_POWER_OFF);
|
||||||
|
addPreferenceHandlerFor(PREF_SOUNDCORE_3D_SURROUND);
|
||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_LDAC_MODE);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_LDAC_MODE);
|
||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_GAMING_MODE);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_GAMING_MODE);
|
||||||
addPreferenceHandlerFor(PREF_SOUNDCORE_ADAPTIVE_DIRECTION);
|
addPreferenceHandlerFor(PREF_SOUNDCORE_ADAPTIVE_DIRECTION);
|
||||||
|
|||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20.SoundcoreSportX20DeviceSupport;
|
||||||
|
|
||||||
|
public class SoundcoreSportX20Coordinator extends AbstractBLClassicDeviceCoordinator {
|
||||||
|
@Override
|
||||||
|
public int getDeviceNameResource() {
|
||||||
|
return R.string.devicetype_soundcore_sport_x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDefaultIconResource() {
|
||||||
|
return R.drawable.ic_device_galaxy_buds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getManufacturer() {
|
||||||
|
return "Anker";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Pattern getSupportedDeviceName() {
|
||||||
|
return Pattern.compile("soundcore Sport X20");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBondingStyle() {
|
||||||
|
return BONDING_STYLE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBatteryCount(final GBDevice device) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsFindDevice(@NonNull final GBDevice device) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BatteryConfig[] getBatteryConfig(final GBDevice device) {
|
||||||
|
final BatteryConfig battery1 = new BatteryConfig(0, R.drawable.ic_buds_pro_case, R.string.battery_case);
|
||||||
|
final BatteryConfig battery2 = new BatteryConfig(1, R.drawable.ic_nothing_ear_l, R.string.left_earbud);
|
||||||
|
final BatteryConfig battery3 = new BatteryConfig(2, R.drawable.ic_nothing_ear_r, R.string.right_earbud);
|
||||||
|
return new BatteryConfig[]{battery1, battery2, battery3};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
|
||||||
|
return new SoundcoreSportX20SettingsCustomizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
|
||||||
|
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
|
||||||
|
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS);
|
||||||
|
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS, R.xml.devicesettings_sony_headphones_ambient_sound_control_button_modes);
|
||||||
|
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS, R.xml.devicesettings_soundcore_sport_x20_touch_options);
|
||||||
|
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.AUDIO);
|
||||||
|
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.AUDIO, R.xml.devicesettings_soundcore_sport_x20_audio);
|
||||||
|
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_soundcore_sport_x20);
|
||||||
|
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS);
|
||||||
|
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS, R.xml.devicesettings_headphones);
|
||||||
|
return deviceSpecificSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceCoordinator.DeviceKind getDeviceKind(@NonNull final GBDevice device) {
|
||||||
|
return DeviceKind.EARBUDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Class<? extends DeviceSupport> getDeviceSupportClass(final GBDevice device) {
|
||||||
|
return SoundcoreSportX20DeviceSupport.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND8_VALUE;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_CUSTOM;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_PRESET;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_RESET;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ENABLE_PAIRING_MODE;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import androidx.preference.ListPreference;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.SeekBarPreference;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20.SoundcoreSportX20Protocol;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
|
public class SoundcoreSportX20SettingsCustomizer implements DeviceSpecificSettingsCustomizer {
|
||||||
|
public static final Creator<SoundcoreSportX20SettingsCustomizer> CREATOR = new Creator<SoundcoreSportX20SettingsCustomizer>() {
|
||||||
|
@Override
|
||||||
|
public SoundcoreSportX20SettingsCustomizer createFromParcel(final Parcel in) {
|
||||||
|
return new SoundcoreSportX20SettingsCustomizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoundcoreSportX20SettingsCustomizer[] newArray(final int size) {
|
||||||
|
return new SoundcoreSportX20SettingsCustomizer[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreferenceChange(final Preference preference, final DeviceSpecificSettingsHandler handler) {
|
||||||
|
if (!PREF_SOUNDCORE_EQUALIZER_PRESET.equals(preference.getKey())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Preference equalizerCustom = handler.findPreference(PREF_SOUNDCORE_EQUALIZER_CUSTOM);
|
||||||
|
if (equalizerCustom == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String preset = ((ListPreference) preference).getValue();
|
||||||
|
equalizerCustom.setEnabled("254".equals(preset));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customizeSettings(final DeviceSpecificSettingsHandler handler, final Prefs prefs, final String rootKey) {
|
||||||
|
final Preference pairingMode = handler.findPreference(PREF_SOUNDCORE_ENABLE_PAIRING_MODE);
|
||||||
|
if (pairingMode != null) {
|
||||||
|
pairingMode.setOnPreferenceClickListener(pref -> {
|
||||||
|
handler.notifyPreferenceChanged(PREF_SOUNDCORE_ENABLE_PAIRING_MODE);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final Preference equalizerCustom = handler.findPreference(PREF_SOUNDCORE_EQUALIZER_CUSTOM);
|
||||||
|
if (equalizerCustom != null) {
|
||||||
|
final String preset = prefs.getString(PREF_SOUNDCORE_EQUALIZER_PRESET, "0");
|
||||||
|
equalizerCustom.setEnabled("254".equals(preset));
|
||||||
|
}
|
||||||
|
|
||||||
|
final Preference equalizerReset = handler.findPreference(PREF_SOUNDCORE_EQUALIZER_RESET);
|
||||||
|
if (equalizerReset != null) {
|
||||||
|
equalizerReset.setOnPreferenceClickListener(pref -> resetEqualizer(handler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean resetEqualizer(final DeviceSpecificSettingsHandler handler) {
|
||||||
|
for (final String key : SoundcoreSportX20Protocol.EQUALIZER_PREFS_VALUE) {
|
||||||
|
final SeekBarPreference pref = handler.findPreference(key);
|
||||||
|
if (pref != null) {
|
||||||
|
pref.setValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.notifyPreferenceChanged(PREF_SOUNDCORE_EQUALIZER_BAND8_VALUE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getPreferenceKeysWithSummary() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
// No-op.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -433,6 +433,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.liberty3_pro.Sound
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.liberty4_nc.SoundcoreLiberty4NCCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.liberty4_nc.SoundcoreLiberty4NCCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.motion300.SoundcoreMotion300Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.motion300.SoundcoreMotion300Coordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.q30.SoundcoreQ30Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.q30.SoundcoreQ30Coordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.sport_x20.SoundcoreSportX20Coordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.supercars.SuperCarsCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.supercars.SuperCarsCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.test.TestDeviceCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.test.TestDeviceCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.thermalprinter.ThermalPrinterCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.thermalprinter.ThermalPrinterCoordinator;
|
||||||
@@ -824,6 +825,7 @@ public enum DeviceType {
|
|||||||
SOUNDCORE_MOTION300(SoundcoreMotion300Coordinator.class),
|
SOUNDCORE_MOTION300(SoundcoreMotion300Coordinator.class),
|
||||||
SOUNDCORE_Q30(SoundcoreQ30Coordinator.class),
|
SOUNDCORE_Q30(SoundcoreQ30Coordinator.class),
|
||||||
SOUNDCORE_AEROFIT2(SoundcoreAeroFit2Coordinator.class),
|
SOUNDCORE_AEROFIT2(SoundcoreAeroFit2Coordinator.class),
|
||||||
|
SOUNDCORE_SPORT_X20(SoundcoreSportX20Coordinator.class),
|
||||||
MOONDROP_SPACE_TRAVEL(MoondropSpaceTravelCoordinator.class),
|
MOONDROP_SPACE_TRAVEL(MoondropSpaceTravelCoordinator.class),
|
||||||
MOONDROP_SPACE_TRAVEL_2(MoondropSpaceTravel2Coordinator.class),
|
MOONDROP_SPACE_TRAVEL_2(MoondropSpaceTravel2Coordinator.class),
|
||||||
BOSE_QC35(QC35Coordinator.class),
|
BOSE_QC35(QC35Coordinator.class),
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractHeadphoneSerialDeviceSupportV2;
|
||||||
|
|
||||||
|
public class SoundcoreSportX20DeviceSupport extends AbstractHeadphoneSerialDeviceSupportV2<SoundcoreSportX20Protocol> {
|
||||||
|
public static final UUID UUID_DEVICE_CTRL = UUID.fromString("0cf12d31-fac3-4553-bd80-d6832e7b3968");
|
||||||
|
|
||||||
|
public SoundcoreSportX20DeviceSupport() {
|
||||||
|
addSupportedService(UUID_DEVICE_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SoundcoreSportX20Protocol createDeviceProtocol() {
|
||||||
|
return new SoundcoreSportX20Protocol(getDevice());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
||||||
|
builder.write(mDeviceProtocol.encodeDeviceInfoRequest());
|
||||||
|
builder.setDeviceState(GBDevice.State.INITIALIZED);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
+379
@@ -0,0 +1,379 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcorePacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.liberty.SoundcoreLibertyProtocol;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
|
public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||||
|
private static final short CMD_SET_EQUALIZER = (short) 0x8703;
|
||||||
|
private static final int CUSTOM_PRESET_ID = 0xfe;
|
||||||
|
private static final int EQ_BANDS = 8;
|
||||||
|
|
||||||
|
public static final String[] EQUALIZER_PREFS_VALUE = new String[]{
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND1_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND2_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND3_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND4_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND5_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND6_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND7_VALUE,
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND8_VALUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int[] EQ_TAIL_SCALE = new int[]{5, 3, 4, 4, 4, 4, 4, 6};
|
||||||
|
private static final int EQ_TAIL_DIVISOR = 6;
|
||||||
|
|
||||||
|
private static final String PRESET_CHANNEL_SEPARATOR = "00";
|
||||||
|
private static final String PRESET_SUFFIX = "0000";
|
||||||
|
private static final String PRESET_COMMON_REPEATED_BLOCK = "9fa18a998a8077643c3c";
|
||||||
|
private static final String PRESET_COMMON_PREFIX = "00000200";
|
||||||
|
private static final String PRESET_COMMON_MIDDLE = "69d64e6a00";
|
||||||
|
private static final String PRESET_COMMON_SECTION =
|
||||||
|
PRESET_COMMON_PREFIX
|
||||||
|
+ PRESET_COMMON_REPEATED_BLOCK
|
||||||
|
+ PRESET_COMMON_REPEATED_BLOCK
|
||||||
|
+ PRESET_COMMON_MIDDLE
|
||||||
|
+ PRESET_COMMON_REPEATED_BLOCK
|
||||||
|
+ PRESET_COMMON_REPEATED_BLOCK;
|
||||||
|
|
||||||
|
private static final Map<Integer, byte[]> EQ_PRESET_PAYLOADS = buildPresetPayloads();
|
||||||
|
|
||||||
|
protected SoundcoreSportX20Protocol(final GBDevice device) {
|
||||||
|
super(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GBDeviceEvent[] decodeResponse(final byte[] responseData) {
|
||||||
|
final ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||||
|
final SoundcorePacket packet = SoundcorePacket.decode(buf);
|
||||||
|
|
||||||
|
if (packet != null && packet.getCommand() == (short) 0x0106) {
|
||||||
|
decodeAncAudioMode(packet.getPayload());
|
||||||
|
return new GBDeviceEvent[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet != null && packet.getCommand() == CMD_SET_EQUALIZER) {
|
||||||
|
decodeEqualizer(packet.getPayload());
|
||||||
|
return new GBDeviceEvent[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.decodeResponse(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encodeSendConfiguration(final String config) {
|
||||||
|
final Prefs prefs = getDevicePrefs();
|
||||||
|
String prefString;
|
||||||
|
|
||||||
|
switch (config) {
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL:
|
||||||
|
return encodeAncAudioMode();
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT, "PLAYPAUSE");
|
||||||
|
return encodeControlFunctionMessage(TapAction.SINGLE_TAP, false, TapFunction.valueOf(prefString));
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT, "PLAYPAUSE");
|
||||||
|
return encodeControlFunctionMessage(TapAction.SINGLE_TAP, true, TapFunction.valueOf(prefString));
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT, "MEDIA_PREV");
|
||||||
|
return encodeControlFunctionMessage(TapAction.DOUBLE_TAP, false, TapFunction.valueOf(prefString));
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT, "MEDIA_NEXT");
|
||||||
|
return encodeControlFunctionMessage(TapAction.DOUBLE_TAP, true, TapFunction.valueOf(prefString));
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT, "AMBIENT_SOUND_CONTROL");
|
||||||
|
return encodeControlFunctionMessage(TapAction.LONG_PRESS, false, TapFunction.valueOf(prefString));
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT:
|
||||||
|
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT, "AMBIENT_SOUND_CONTROL");
|
||||||
|
return encodeControlFunctionMessage(TapAction.LONG_PRESS, true, TapFunction.valueOf(prefString));
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AUTO_POWER_OFF:
|
||||||
|
final int duration = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AUTO_POWER_OFF, "3"));
|
||||||
|
return encodeAutoPowerOff(duration);
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE:
|
||||||
|
final boolean pressAlert = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE, false);
|
||||||
|
return new SoundcorePacket((short) 0x8301, new byte[]{encodeBoolean(pressAlert)}).encode();
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_3D_SURROUND:
|
||||||
|
final boolean surround3d = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_3D_SURROUND, false);
|
||||||
|
return new SoundcorePacket((short) 0x8602, new byte[]{encodeBoolean(surround3d)}).encode();
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_PRESET:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND1_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND2_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND3_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND4_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND5_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND6_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND7_VALUE:
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND8_VALUE:
|
||||||
|
return encodeEqualizer();
|
||||||
|
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ENABLE_PAIRING_MODE:
|
||||||
|
return new SoundcorePacket((short) 0x850b, new byte[]{0x00, (byte) 0x90}).encode();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return super.encodeSendConfiguration(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encodeFindDevice(final boolean start) {
|
||||||
|
final boolean findLeft = start;
|
||||||
|
final boolean findRight = start;
|
||||||
|
final byte[] payload = new byte[]{encodeBoolean(findLeft), encodeBoolean(findRight), 0x00};
|
||||||
|
return new SoundcorePacket((short) 0x8910, payload).encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] encodeControlFunctionMessage(final TapAction action, final boolean right, final TapFunction function) {
|
||||||
|
final byte functionByte;
|
||||||
|
switch (action) {
|
||||||
|
case SINGLE_TAP:
|
||||||
|
functionByte = (byte) (16 * 6 + function.getCode());
|
||||||
|
break;
|
||||||
|
case DOUBLE_TAP:
|
||||||
|
functionByte = (byte) (16 * 3 + function.getCode());
|
||||||
|
break;
|
||||||
|
case LONG_PRESS:
|
||||||
|
functionByte = (byte) (16 * 4 + function.getCode());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] payload = new byte[]{encodeBoolean(right), action.getCode(), functionByte};
|
||||||
|
return new SoundcorePacket((short) 0x8104, payload).encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0: No Auto Power off
|
||||||
|
* 1: Auto Power off 10 min
|
||||||
|
* 2: Auto Power off 20 min
|
||||||
|
* 3: Auto Power off 30 min
|
||||||
|
* 4: Auto Power off 60 min
|
||||||
|
*/
|
||||||
|
private byte[] encodeAutoPowerOff(final int duration) {
|
||||||
|
final byte[] payload;
|
||||||
|
|
||||||
|
if (duration > 0) {
|
||||||
|
payload = new byte[]{(byte) 0x01, (byte) (duration - 1)};
|
||||||
|
} else {
|
||||||
|
payload = new byte[]{(byte) 0x00, (byte) 0x03};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SoundcorePacket((short) 0x8601, payload).encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decodeAncAudioMode(final byte[] payload) {
|
||||||
|
if (payload.length < 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||||
|
final SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
|
||||||
|
String ambientSoundMode = "off";
|
||||||
|
if (payload[0] == 0x00) {
|
||||||
|
ambientSoundMode = "noise_cancelling";
|
||||||
|
} else if (payload[0] == 0x01) {
|
||||||
|
ambientSoundMode = "ambient_sound";
|
||||||
|
} else if (payload[0] == 0x02) {
|
||||||
|
ambientSoundMode = "off";
|
||||||
|
}
|
||||||
|
|
||||||
|
int ancStrength = ((payload[1] & 0x30) >> 4) - 1;
|
||||||
|
|
||||||
|
final boolean vocalMode = (payload[2] == 0x01);
|
||||||
|
final boolean adaptiveAnc = (payload[3] == 0x01);
|
||||||
|
final boolean windNoiseReduction = (payload[4] == 0x01);
|
||||||
|
|
||||||
|
editor.putString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, ambientSoundMode);
|
||||||
|
editor.putInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, ancStrength);
|
||||||
|
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, vocalMode);
|
||||||
|
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, adaptiveAnc);
|
||||||
|
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, windNoiseReduction);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] encodeAncAudioMode() {
|
||||||
|
final Prefs prefs = getDevicePrefs();
|
||||||
|
|
||||||
|
final String ambientMode = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off");
|
||||||
|
final int ancStrengthValue = prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0);
|
||||||
|
final boolean vocalMode = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false);
|
||||||
|
final boolean adaptive = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true);
|
||||||
|
final boolean windReduction = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false);
|
||||||
|
|
||||||
|
if (ancStrengthValue < 0 || ancStrengthValue > 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final byte ancStrengthByte = (byte) ((ancStrengthValue + 1) << 4);
|
||||||
|
|
||||||
|
final byte ambientModeByte;
|
||||||
|
switch (ambientMode) {
|
||||||
|
case "noise_cancelling":
|
||||||
|
ambientModeByte = 0x00;
|
||||||
|
break;
|
||||||
|
case "ambient_sound":
|
||||||
|
ambientModeByte = 0x01;
|
||||||
|
break;
|
||||||
|
case "off":
|
||||||
|
ambientModeByte = 0x02;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte adaptiveByte = encodeBoolean(adaptive);
|
||||||
|
final byte vocalModeByte = encodeBoolean(vocalMode);
|
||||||
|
final byte windReductionByte = encodeBoolean(windReduction);
|
||||||
|
|
||||||
|
final byte[] payload = new byte[]{ambientModeByte, ancStrengthByte, vocalModeByte, adaptiveByte, windReductionByte};
|
||||||
|
return new SoundcorePacket((short) 0x8106, payload).encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] encodeEqualizer() {
|
||||||
|
final Prefs prefs = getDevicePrefs();
|
||||||
|
final int preset = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_PRESET, "0"));
|
||||||
|
|
||||||
|
if (preset != CUSTOM_PRESET_ID) {
|
||||||
|
final byte[] presetPayload = EQ_PRESET_PAYLOADS.get(preset);
|
||||||
|
if (presetPayload != null) {
|
||||||
|
return new SoundcorePacket(CMD_SET_EQUALIZER, presetPayload).encode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] rawBands = new int[EQ_BANDS];
|
||||||
|
final int[] tailBands = new int[EQ_BANDS];
|
||||||
|
|
||||||
|
for (int i = 0; i < EQ_BANDS; i++) {
|
||||||
|
final int value = clamp(prefs.getInt(EQUALIZER_PREFS_VALUE[i], 0), -6, 6);
|
||||||
|
|
||||||
|
rawBands[i] = 120 + (value * 10);
|
||||||
|
tailBands[i] = 120 + Math.round((float) (value * EQ_TAIL_SCALE[i]) / EQ_TAIL_DIVISOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] payload = buildPresetPayload(
|
||||||
|
CUSTOM_PRESET_ID,
|
||||||
|
bandsToHex(rawBands),
|
||||||
|
bandsToHex(tailBands)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SoundcorePacket(CMD_SET_EQUALIZER, payload).encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decodeEqualizer(final byte[] payload) {
|
||||||
|
if (payload.length < 90) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int preset = Byte.toUnsignedInt(payload[0]);
|
||||||
|
final SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||||
|
final SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
|
||||||
|
editor.putString(
|
||||||
|
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_PRESET,
|
||||||
|
String.valueOf(preset)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (int i = 0; i < EQ_BANDS; i++) {
|
||||||
|
final int rawBand = Byte.toUnsignedInt(payload[4 + i]);
|
||||||
|
final int value = clamp(Math.round((rawBand - 120) / 10f), -6, 6);
|
||||||
|
editor.putInt(EQUALIZER_PREFS_VALUE[i], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Integer, byte[]> buildPresetPayloads() {
|
||||||
|
final Map<Integer, byte[]> presetPayloads = new HashMap<>();
|
||||||
|
|
||||||
|
presetPayloads.put(0x00, buildPresetPayload(0x00, "787878787878787878", "787878787878787878"));
|
||||||
|
presetPayloads.put(0x01, buildPresetPayload(0x01, "a0828c8ca0a0a08c78", "7d767b787c7a7c7978"));
|
||||||
|
presetPayloads.put(0x02, buildPresetPayload(0x02, "a09682787878787878", "7b7a78787878787878"));
|
||||||
|
presetPayloads.put(0x03, buildPresetPayload(0x03, "505a6e787878787878", "757678787878787878"));
|
||||||
|
presetPayloads.put(0x04, buildPresetPayload(0x04, "96966464788c96a078", "7a7c7477787a797d78"));
|
||||||
|
presetPayloads.put(0x05, buildPresetPayload(0x05, "5a8ca0a0968c786478", "747b7a7b797a787578"));
|
||||||
|
presetPayloads.put(0x06, buildPresetPayload(0x06, "8c5a6e828c8c825a78", "7c7378787a797b7378"));
|
||||||
|
presetPayloads.put(0x07, buildPresetPayload(0x07, "8c8296968c64504678", "7a777b797b76767378"));
|
||||||
|
presetPayloads.put(0x08, buildPresetPayload(0x08, "968c648c828c969678", "7a7b737d777a7a7b78"));
|
||||||
|
presetPayloads.put(0x09, buildPresetPayload(0x09, "64646e787878646478", "767777787879767678"));
|
||||||
|
presetPayloads.put(0x0a, buildPresetPayload(0x0a, "8c966e6e8c6e8c9678", "797c76767d747b7b78"));
|
||||||
|
presetPayloads.put(0x0b, buildPresetPayload(0x0b, "8c8c6464788c96a078", "797b7577787a797d78"));
|
||||||
|
presetPayloads.put(0x0c, buildPresetPayload(0x0c, "78786464647896aa78", "7879767776787a7e78"));
|
||||||
|
presetPayloads.put(0x0d, buildPresetPayload(0x0d, "6e8ca09678648c8278", "767a7b7a78747c7878"));
|
||||||
|
presetPayloads.put(0x0e, buildPresetPayload(0x0e, "7896968ca0aa96a078", "777b7a787b7c787d78"));
|
||||||
|
presetPayloads.put(0x0f, buildPresetPayload(0x0f, "6e829696826e645a78", "77797a7a7977777578"));
|
||||||
|
presetPayloads.put(0x10, buildPresetPayload(0x10, "b48c64648c9696a078", "7e7976757b7a797d78"));
|
||||||
|
presetPayloads.put(0x11, buildPresetPayload(0x11, "968c6e6e8296a0aa78", "7a7a7677797a7a7e78"));
|
||||||
|
presetPayloads.put(0x12, buildPresetPayload(0x12, "a0968278645a505078", "7b7a78797676757478"));
|
||||||
|
presetPayloads.put(0x13, buildPresetPayload(0x13, "5a64828c8c82785a78", "76767a797a78797478"));
|
||||||
|
presetPayloads.put(0x14, buildPresetPayload(0x14, "6464646e828c8ca078", "76777777797a787d78"));
|
||||||
|
presetPayloads.put(0x15, buildPresetPayload(0x15, "787878645a50503c78", "787879767775777178"));
|
||||||
|
|
||||||
|
return presetPayloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] buildPresetPayload(final int presetId, final String bands, final String tails) {
|
||||||
|
return decodeHex(
|
||||||
|
toHexByte(presetId)
|
||||||
|
+ "000000"
|
||||||
|
+ bands
|
||||||
|
+ PRESET_CHANNEL_SEPARATOR
|
||||||
|
+ bands
|
||||||
|
+ PRESET_COMMON_SECTION
|
||||||
|
+ tails
|
||||||
|
+ PRESET_CHANNEL_SEPARATOR
|
||||||
|
+ tails
|
||||||
|
+ PRESET_SUFFIX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bandsToHex(final int[] bands) {
|
||||||
|
final StringBuilder sb = new StringBuilder(bands.length * 2);
|
||||||
|
|
||||||
|
for (final int band : bands) {
|
||||||
|
sb.append(toHexByte(band));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toHexByte(final int value) {
|
||||||
|
final String hex = Integer.toHexString(value & 0xff);
|
||||||
|
return hex.length() < 2 ? "0" + hex : hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] decodeHex(final String hex) {
|
||||||
|
final int len = hex.length();
|
||||||
|
final byte[] data = new byte[len / 2];
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
||||||
|
+ Character.digit(hex.charAt(i + 1), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clamp(final int value, final int min, final int max) {
|
||||||
|
return Math.max(min, Math.min(max, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
enum TapAction {
|
||||||
|
SINGLE_TAP((byte) 0x02),
|
||||||
|
DOUBLE_TAP((byte) 0x00),
|
||||||
|
LONG_PRESS((byte) 0x01)
|
||||||
|
;
|
||||||
|
|
||||||
|
private final byte code;
|
||||||
|
|
||||||
|
TapAction(final byte code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20;
|
||||||
|
|
||||||
|
enum TapFunction {
|
||||||
|
VOLUME_DOWN(1),
|
||||||
|
VOLUME_UP(0),
|
||||||
|
MEDIA_NEXT(3),
|
||||||
|
MEDIA_PREV(2),
|
||||||
|
PLAYPAUSE(6),
|
||||||
|
VOICE_ASSISTANT(5),
|
||||||
|
AMBIENT_SOUND_CONTROL(4),
|
||||||
|
NONE(15)
|
||||||
|
;
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
TapFunction(final int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4567,6 +4567,120 @@
|
|||||||
<item>AMBIENT_SOUND_CONTROL</item>
|
<item>AMBIENT_SOUND_CONTROL</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_single_tap_function_names">
|
||||||
|
<item>@string/pref_media_volumedown</item>
|
||||||
|
<item>@string/pref_media_volumeup</item>
|
||||||
|
<item>@string/pref_media_next</item>
|
||||||
|
<item>@string/pref_media_previous</item>
|
||||||
|
<item>@string/pref_media_playpause</item>
|
||||||
|
<item>@string/none</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_single_tap_function_values">
|
||||||
|
<item>VOLUME_DOWN</item>
|
||||||
|
<item>VOLUME_UP</item>
|
||||||
|
<item>MEDIA_NEXT</item>
|
||||||
|
<item>MEDIA_PREV</item>
|
||||||
|
<item>PLAYPAUSE</item>
|
||||||
|
<item>NONE</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_double_tap_function_names">
|
||||||
|
<item>@string/pref_media_volumedown</item>
|
||||||
|
<item>@string/pref_media_volumeup</item>
|
||||||
|
<item>@string/pref_media_next</item>
|
||||||
|
<item>@string/pref_media_previous</item>
|
||||||
|
<item>@string/pref_media_playpause</item>
|
||||||
|
<item>@string/pref_title_touch_voice_assistant</item>
|
||||||
|
<item>@string/sony_button_mode_ambient_sound_control</item>
|
||||||
|
<item>@string/none</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_double_tap_function_values">
|
||||||
|
<item>VOLUME_DOWN</item>
|
||||||
|
<item>VOLUME_UP</item>
|
||||||
|
<item>MEDIA_NEXT</item>
|
||||||
|
<item>MEDIA_PREV</item>
|
||||||
|
<item>PLAYPAUSE</item>
|
||||||
|
<item>VOICE_ASSISTANT</item>
|
||||||
|
<item>AMBIENT_SOUND_CONTROL</item>
|
||||||
|
<item>NONE</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_long_press_function_names">
|
||||||
|
<item>@string/pref_media_volumedown</item>
|
||||||
|
<item>@string/pref_media_volumeup</item>
|
||||||
|
<item>@string/pref_media_next</item>
|
||||||
|
<item>@string/pref_media_previous</item>
|
||||||
|
<item>@string/pref_media_playpause</item>
|
||||||
|
<item>@string/pref_title_touch_voice_assistant</item>
|
||||||
|
<item>@string/sony_button_mode_ambient_sound_control</item>
|
||||||
|
<item>@string/none</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_long_press_function_values">
|
||||||
|
<item>VOLUME_DOWN</item>
|
||||||
|
<item>VOLUME_UP</item>
|
||||||
|
<item>MEDIA_NEXT</item>
|
||||||
|
<item>MEDIA_PREV</item>
|
||||||
|
<item>PLAYPAUSE</item>
|
||||||
|
<item>VOICE_ASSISTANT</item>
|
||||||
|
<item>AMBIENT_SOUND_CONTROL</item>
|
||||||
|
<item>NONE</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_equalizer_preset_names">
|
||||||
|
<item>@string/soundcore_equalizer_preset_signature</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_acoustic</item>
|
||||||
|
<item>@string/sony_equalizer_preset_bass_boost</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_bass_reducer</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_classical</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_podcast</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_dance</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_deep</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_electronic</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_flat</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_hip_hop</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_jazz</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_latin</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_lounge</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_piano</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_pop</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_rnb</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_rock</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_small_speakers</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_spoken_word</item>
|
||||||
|
<item>@string/sony_equalizer_preset_treble_boost</item>
|
||||||
|
<item>@string/soundcore_equalizer_preset_treble_reducer</item>
|
||||||
|
<item>@string/custom</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="soundcore_sport_x20_equalizer_preset_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
|
<item>9</item>
|
||||||
|
<item>10</item>
|
||||||
|
<item>11</item>
|
||||||
|
<item>12</item>
|
||||||
|
<item>13</item>
|
||||||
|
<item>14</item>
|
||||||
|
<item>15</item>
|
||||||
|
<item>16</item>
|
||||||
|
<item>17</item>
|
||||||
|
<item>18</item>
|
||||||
|
<item>19</item>
|
||||||
|
<item>20</item>
|
||||||
|
<item>21</item>
|
||||||
|
<item>254</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="soundcore_button_brightness_names">
|
<string-array name="soundcore_button_brightness_names">
|
||||||
<item>@string/off</item>
|
<item>@string/off</item>
|
||||||
<item>@string/soundcore_button_brightness_low</item>
|
<item>@string/soundcore_button_brightness_low</item>
|
||||||
|
|||||||
@@ -2146,6 +2146,7 @@
|
|||||||
<string name="devicetype_soundcore_motion300" translatable="false">Soundcore Motion 300</string>
|
<string name="devicetype_soundcore_motion300" translatable="false">Soundcore Motion 300</string>
|
||||||
<string name="devicetype_soundcore_q30" translatable="false">Soundcore Q30</string>
|
<string name="devicetype_soundcore_q30" translatable="false">Soundcore Q30</string>
|
||||||
<string name="devicetype_soundcore_aerofit2" translatable="false">Soundcore AeroFit 2</string>
|
<string name="devicetype_soundcore_aerofit2" translatable="false">Soundcore AeroFit 2</string>
|
||||||
|
<string name="devicetype_soundcore_sport_x20" translatable="false">Soundcore Sport X20</string>
|
||||||
<string name="devicetype_pixel_buds_a_series" translatable="false">Pixel Buds A-Series</string>
|
<string name="devicetype_pixel_buds_a_series" translatable="false">Pixel Buds A-Series</string>
|
||||||
<string name="devicetype_moondrop_space_travel" translatable="false">Moondrop Space Travel</string>
|
<string name="devicetype_moondrop_space_travel" translatable="false">Moondrop Space Travel</string>
|
||||||
<string name="devicetype_moondrop_space_travel_2" translatable="false">Moondrop Space Travel 2</string>
|
<string name="devicetype_moondrop_space_travel_2" translatable="false">Moondrop Space Travel 2</string>
|
||||||
@@ -3517,6 +3518,9 @@
|
|||||||
<string name="soundcore_ldac_mode_summary">Enabling LDAC will decrease the battery life and might lead to connection instability</string>
|
<string name="soundcore_ldac_mode_summary">Enabling LDAC will decrease the battery life and might lead to connection instability</string>
|
||||||
<string name="soundcore_auto_power_off_title">Auto Power Off</string>
|
<string name="soundcore_auto_power_off_title">Auto Power Off</string>
|
||||||
<string name="soundcore_auto_power_off_summary">When disconnectiong from the phone, the device will power off after the specified timeout</string>
|
<string name="soundcore_auto_power_off_summary">When disconnectiong from the phone, the device will power off after the specified timeout</string>
|
||||||
|
<string name="soundcore_3d_surround_title">3D Surround Sound</string>
|
||||||
|
<string name="soundcore_3d_surround_summary">Enable 3D surrounding sound</string>
|
||||||
|
<string name="soundcore_enable_pairing_mode_summary">Enable discovery/pairing mode to connect a new device</string>
|
||||||
<string name="soundcore_battery_low_tone_title">Low Battery Tone</string>
|
<string name="soundcore_battery_low_tone_title">Low Battery Tone</string>
|
||||||
<string name="soundcore_battery_low_tone_summary">Hear the prompt tone when the battery level is below 20% and 10%</string>
|
<string name="soundcore_battery_low_tone_summary">Hear the prompt tone when the battery level is below 20% and 10%</string>
|
||||||
<string name="soundcore_gaming_mode_title">Gaming Mode</string>
|
<string name="soundcore_gaming_mode_title">Gaming Mode</string>
|
||||||
@@ -3528,6 +3532,25 @@
|
|||||||
<string name="soundcore_equalizer_preset_xtra_bass">Xtra Bass</string>
|
<string name="soundcore_equalizer_preset_xtra_bass">Xtra Bass</string>
|
||||||
<string name="soundcore_equalizer_preset_voice">Voice</string>
|
<string name="soundcore_equalizer_preset_voice">Voice</string>
|
||||||
<string name="soundcore_equalizer_preset_balanced">Balanced</string>
|
<string name="soundcore_equalizer_preset_balanced">Balanced</string>
|
||||||
|
<string name="soundcore_equalizer_preset_acoustic">Acoustic</string>
|
||||||
|
<string name="soundcore_equalizer_preset_bass_reducer">Bass Reducer</string>
|
||||||
|
<string name="soundcore_equalizer_preset_classical">Classical</string>
|
||||||
|
<string name="soundcore_equalizer_preset_podcast">Podcast</string>
|
||||||
|
<string name="soundcore_equalizer_preset_dance">Dance</string>
|
||||||
|
<string name="soundcore_equalizer_preset_deep">Deep</string>
|
||||||
|
<string name="soundcore_equalizer_preset_electronic">Electronic</string>
|
||||||
|
<string name="soundcore_equalizer_preset_flat">Flat</string>
|
||||||
|
<string name="soundcore_equalizer_preset_hip_hop">Hip-Hop</string>
|
||||||
|
<string name="soundcore_equalizer_preset_jazz">Jazz</string>
|
||||||
|
<string name="soundcore_equalizer_preset_latin">Latin</string>
|
||||||
|
<string name="soundcore_equalizer_preset_lounge">Lounge</string>
|
||||||
|
<string name="soundcore_equalizer_preset_piano">Piano</string>
|
||||||
|
<string name="soundcore_equalizer_preset_pop">Pop</string>
|
||||||
|
<string name="soundcore_equalizer_preset_rnb">R&B</string>
|
||||||
|
<string name="soundcore_equalizer_preset_rock">Rock</string>
|
||||||
|
<string name="soundcore_equalizer_preset_small_speakers">Small Speakers</string>
|
||||||
|
<string name="soundcore_equalizer_preset_spoken_word">Spoken Word</string>
|
||||||
|
<string name="soundcore_equalizer_preset_treble_reducer">Treble Reducer</string>
|
||||||
<string name="soundcore_equalizer_custom_title">Customize…</string>
|
<string name="soundcore_equalizer_custom_title">Customize…</string>
|
||||||
<string name="soundcore_equalizer_custom_summary">Configure parametric equalizer settings</string>
|
<string name="soundcore_equalizer_custom_summary">Configure parametric equalizer settings</string>
|
||||||
<string name="soundcore_equalizer_direction">Device Direction</string>
|
<string name="soundcore_equalizer_direction">Device Direction</string>
|
||||||
@@ -3547,6 +3570,14 @@
|
|||||||
<string name="soundcore_equalizer_band9">Band 9</string>
|
<string name="soundcore_equalizer_band9">Band 9</string>
|
||||||
<string name="soundcore_equalizer_frequency">Frequency</string>
|
<string name="soundcore_equalizer_frequency">Frequency</string>
|
||||||
<string name="soundcore_equalizer_value">Value</string>
|
<string name="soundcore_equalizer_value">Value</string>
|
||||||
|
<string name="soundcore_equalizer_band1_freq">100 Hz</string>
|
||||||
|
<string name="soundcore_equalizer_band2_freq">200 Hz</string>
|
||||||
|
<string name="soundcore_equalizer_band3_freq">400 Hz</string>
|
||||||
|
<string name="soundcore_equalizer_band4_freq">800 Hz</string>
|
||||||
|
<string name="soundcore_equalizer_band5_freq">1.6 kHz</string>
|
||||||
|
<string name="soundcore_equalizer_band6_freq">3.2 kHz</string>
|
||||||
|
<string name="soundcore_equalizer_band7_freq">6.4 kHz</string>
|
||||||
|
<string name="soundcore_equalizer_band8_freq">12.8 kHz</string>
|
||||||
<string name="miscale_weight_unit_title">Weight Unit</string>
|
<string name="miscale_weight_unit_title">Weight Unit</string>
|
||||||
<string name="miscale_weight_unit_summary">Set unit of weight for displayed measurements</string>
|
<string name="miscale_weight_unit_summary">Set unit of weight for displayed measurements</string>
|
||||||
<string name="miscale_weight_unit_metric">Metric (kg)</string>
|
<string name="miscale_weight_unit_metric">Metric (kg)</string>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_key_header_soundcore_ambient_sound_control"
|
||||||
|
android:title="@string/pref_header_sony_ambient_sound_control">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="noise_cancelling"
|
||||||
|
android:entries="@array/sony_ambient_sound_control_names"
|
||||||
|
android:entryValues="@array/sony_ambient_sound_control_values"
|
||||||
|
android:icon="@drawable/ic_hearing"
|
||||||
|
android:key="pref_soundcore_ambient_sound_control"
|
||||||
|
android:title="@string/sony_ambient_sound"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:disableDependentsState="true"
|
||||||
|
android:icon="@drawable/ic_hearing"
|
||||||
|
android:key="pref_adaptive_noise_cancelling"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:summary="@string/pref_adaptive_noise_cancelling_summary"
|
||||||
|
android:title="@string/pref_adaptive_noise_cancelling_title" />
|
||||||
|
|
||||||
|
<SeekBarPreference
|
||||||
|
android:dependency="pref_adaptive_noise_cancelling"
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_hearing"
|
||||||
|
android:key="pref_sony_ambient_sound_level"
|
||||||
|
android:max="2"
|
||||||
|
android:title="@string/prefs_active_noise_cancelling_level" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_block"
|
||||||
|
android:key="pref_soundcore_wind_noise_reduction"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:title="@string/sony_ambient_sound_wind_noise_reduction" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_voice"
|
||||||
|
android:key="pref_soundcore_transparency_vocal_mode"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:title="@string/sony_ambient_sound_focus_voice" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_key_header_soundcore_general"
|
||||||
|
android:title="@string/pref_header_general">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="3"
|
||||||
|
android:entries="@array/soundcore_aerofit_auto_power_off_names"
|
||||||
|
android:entryValues="@array/soundcore_auto_power_off_values"
|
||||||
|
android:icon="@drawable/ic_power_settings_new"
|
||||||
|
android:key="pref_soundcore_auto_power_off"
|
||||||
|
android:summary="@string/soundcore_auto_power_off_summary"
|
||||||
|
android:title="@string/soundcore_auto_power_off_title" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_soundcore_touch_tone"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:summary="@string/pref_touch_tone_summary"
|
||||||
|
android:title="@string/pref_touch_tone" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="pref_soundcore_enable_pairing_mode"
|
||||||
|
android:summary="@string/soundcore_enable_pairing_mode_summary"
|
||||||
|
android:title="@string/bluetooth_multipoint_pair_new" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</androidx.preference.PreferenceScreen>
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_soundcore_3d_surround"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:summary="@string/soundcore_3d_surround_summary"
|
||||||
|
android:title="@string/soundcore_3d_surround_title" />
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/pref_header_equalizer">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:entries="@array/soundcore_sport_x20_equalizer_preset_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_equalizer_preset_values"
|
||||||
|
android:icon="@drawable/ic_equalizer"
|
||||||
|
android:key="pref_soundcore_equalizer_preset"
|
||||||
|
android:title="@string/soundcore_equalizer_preset"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_custom"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/soundcore_equalizer_custom_summary"
|
||||||
|
android:title="@string/soundcore_equalizer_custom_title">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:icon="@drawable/ic_history"
|
||||||
|
android:key="pref_soundcore_equalizer_reset"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/soundcore_equalizer_reset_summary"
|
||||||
|
android:title="@string/soundcore_equalizer_reset_title" />
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band1_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band1_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band2_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band2_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band3_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band3_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band4_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band4_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band5_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band5_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band6_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band6_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band7_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band7_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/soundcore_equalizer_band8_freq">
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:icon="@drawable/ic_graphic_eq"
|
||||||
|
android:key="pref_soundcore_equalizer_band8_value"
|
||||||
|
android:max="6"
|
||||||
|
android:title="@string/soundcore_equalizer_value"
|
||||||
|
app:min="-6"
|
||||||
|
app:showSeekBarValue="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</androidx.preference.PreferenceScreen>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/single_tap">
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_single_tap_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_single_tap_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_single_tap_action_left"
|
||||||
|
android:title="@string/prefs_left"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_single_tap_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_single_tap_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_single_tap_action_right"
|
||||||
|
android:title="@string/prefs_right"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/double_tap">
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_double_tap_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_double_tap_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_double_tap_action_left"
|
||||||
|
android:title="@string/prefs_left"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_double_tap_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_double_tap_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_double_tap_action_right"
|
||||||
|
android:title="@string/prefs_right"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/long_press">
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_long_press_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_long_press_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_long_press_action_left"
|
||||||
|
android:title="@string/prefs_left"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/soundcore_sport_x20_long_press_function_names"
|
||||||
|
android:entryValues="@array/soundcore_sport_x20_long_press_function_values"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_soundcore_control_long_press_action_right"
|
||||||
|
android:title="@string/prefs_right"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</androidx.preference.PreferenceScreen>
|
||||||
Reference in New Issue
Block a user