mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Add EarFun Free Pro 3 support
New device integration based on the EarFun Air Pro 4 implementation, adapted to match the Free Pro 3 specifications: - Qualcomm QCC3072, Bluetooth 5.3 - Codecs: SBC, AAC, aptX, aptX Adaptive (no LDAC, no LC3) - 10-band equalizer - Hybrid ANC (4 modes: ANC, wind noise, ambient, normal) - 6-mic array with cVc 8.0 - Game mode (<55ms low latency) - Multipoint (2 devices) - 3 batteries (left, right, case) - Touch gestures (single/double/triple/long press per earbud) Differences from Air Pro 4: - No LDAC codec, only aptX + aptX Adaptive - No LE Audio / Advanced Audio Mode - No in-ear detection setting Detection: name "EarFun Free Pro 3", MAC prefix 70:5A:6F, 9 SDP UUIDs (includes 0000110c AVRCP Target, excludes Air Pro 4's df21fe2c/180f/180a UUIDs).
This commit is contained in:
+120
@@ -0,0 +1,120 @@
|
||||
/* Copyright (C) 2026 Obside
|
||||
|
||||
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.devices.earfun;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
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.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.freepro3.EarFunFreePro3DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.freepro3.EarFunFreePro3SettingsCustomizer;
|
||||
|
||||
public class EarFunFreePro3Coordinator extends AbstractEarFunCoordinator {
|
||||
@Override
|
||||
public int getDeviceNameResource() {
|
||||
return R.string.devicetype_earfun_free_pro_3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
if (candidate.getName().startsWith("EarFun Free Pro 3")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// fallback: check UUIDs and MAC prefix to detect even if device name was changed
|
||||
// Free Pro 3 has 9 UUIDs: 5 standard audio + 4 vendor (EB04-EB07)
|
||||
// Same MAC prefix (70:5A:6F) as Air Pro 4, so we must distinguish by UUID set
|
||||
String[] uuids = {
|
||||
"00001101-0000-1000-8000-00805f9b34fb",
|
||||
"0000111e-0000-1000-8000-00805f9b34fb",
|
||||
"0000110b-0000-1000-8000-00805f9b34fb",
|
||||
"0000110c-0000-1000-8000-00805f9b34fb",
|
||||
"0000110e-0000-1000-8000-00805f9b34fb",
|
||||
"0000eb04-d102-11e1-9b23-00025b00a5a5",
|
||||
"0000eb06-d102-11e1-9b23-00025b00a5a5",
|
||||
"0000eb07-d102-11e1-9b23-00025b00a5a5",
|
||||
"0000eb05-d102-11e1-9b23-00025b00a5a5"};
|
||||
|
||||
boolean allServicesSupported = Arrays.stream(uuids)
|
||||
.map(UUID::fromString)
|
||||
.map(candidate::supportsService).allMatch(b -> b);
|
||||
|
||||
// Must NOT have Air Pro 4 extras (df21fe2c, 180f battery, 180a device info)
|
||||
boolean hasAirPro4Extras = candidate.supportsService(
|
||||
UUID.fromString("df21fe2c-2515-4fdb-8886-f12c4d67927c"));
|
||||
|
||||
boolean macAddressMatches = candidate.getMacAddress().toUpperCase().startsWith("70:5A:6F");
|
||||
|
||||
return allServicesSupported && !hasAirPro4Extras && macAddressMatches;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Class<? extends DeviceSupport> getDeviceSupportClass(final GBDevice device) {
|
||||
return EarFunFreePro3DeviceSupport.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatteryCount(final GBDevice device) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatteryConfig[] getBatteryConfig(final GBDevice device) {
|
||||
BatteryConfig battery1 = new BatteryConfig(2, R.drawable.ic_buds_pro_case, R.string.battery_case);
|
||||
BatteryConfig battery2 = new BatteryConfig(0, R.drawable.ic_nothing_ear_l, R.string.left_earbud);
|
||||
BatteryConfig battery3 = new BatteryConfig(1, R.drawable.ic_nothing_ear_r, R.string.right_earbud);
|
||||
return new BatteryConfig[]{battery1, battery2, battery3};
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
|
||||
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
|
||||
// Category Audio Experience
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_header_audio_experience);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_10_band_equalizer);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_free_pro_3_sound_control);
|
||||
|
||||
// Category Audio Quality & Connectivity
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_header_connectivity);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_free_pro_3_audio_quality);
|
||||
|
||||
// Category System Settings
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_header_system_settings);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_free_pro_3_gestures);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_find_device);
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_earfun_device_name);
|
||||
final List<Integer> callsAndNotif = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS);
|
||||
callsAndNotif.add(R.xml.devicesettings_headphones);
|
||||
return deviceSpecificSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
|
||||
return new EarFunFreePro3SettingsCustomizer(device);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.cycling_sensor.coordinator.C
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.divoom.PixooCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.domyos.DomyosT540Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.earfun.EarFunAirPro4Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.earfun.EarFunFreePro3Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.earfun.EarFunAirSCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.evenrealities.G1DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.femometer.FemometerVinca2DeviceCoordinator;
|
||||
@@ -969,6 +970,7 @@ public enum DeviceType {
|
||||
B_AND_W_P_SERIES(BandWPSeriesDeviceCoordinator.class),
|
||||
EARFUN_AIR_S(EarFunAirSCoordinator.class),
|
||||
EARFUN_AIR_PRO_4(EarFunAirPro4Coordinator.class),
|
||||
EARFUN_FREE_PRO_3(EarFunFreePro3Coordinator.class),
|
||||
SCANNABLE(ScannableDeviceCoordinator.class),
|
||||
CYCLING_SENSOR(CyclingSensorCoordinator.class),
|
||||
BLE_GATT_CLIENT(BleGattClientCoordinator.class),
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/* Copyright (C) 2026 Obside
|
||||
|
||||
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.service.devices.earfun.freepro3;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.EarFunDeviceSupport;
|
||||
|
||||
public class EarFunFreePro3DeviceSupport extends EarFunDeviceSupport {
|
||||
|
||||
@Override
|
||||
protected EarFunFreePro3Protocol createDeviceProtocol() {
|
||||
return new EarFunFreePro3Protocol(getDevice());
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/* Copyright (C) 2026 Obside
|
||||
|
||||
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.service.devices.earfun.freepro3;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.EarFunPacketEncoder.joinPackets;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.EarFunPacketEncoder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.EarFunProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.Equalizer;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class EarFunFreePro3Protocol extends EarFunProtocol {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(EarFunFreePro3Protocol.class);
|
||||
|
||||
@Override
|
||||
public byte[] encodeTestNewFunction(@Nullable Bundle options) {
|
||||
return joinPackets(
|
||||
// new EarFunPacket(EarFunPacket.Command.COMMAND_REBOOT).encode()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeSendConfiguration(String config) {
|
||||
if (Equalizer.containsKey(Equalizer.TenBandEqualizer, config)) {
|
||||
Prefs prefs = getDevicePrefs();
|
||||
return EarFunPacketEncoder.encodeSetEqualizerTenBands(prefs);
|
||||
}
|
||||
return super.encodeSendConfiguration(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeSettingsReq() {
|
||||
return EarFunPacketEncoder.encodeAirPro4SettingsReq();
|
||||
}
|
||||
|
||||
protected EarFunFreePro3Protocol(GBDevice device) {
|
||||
super(device);
|
||||
DeviceType type = device.getType();
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/* Copyright (C) 2026 Obside
|
||||
|
||||
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.service.devices.earfun.freepro3;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.EarFunSettingsPreferenceConst.PREF_EARFUN_AMBIENT_SOUND_CONTROL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.EarFunSettingsPreferenceConst.PREF_EARFUN_ANC_MODE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.EarFunSettingsPreferenceConst.PREF_EARFUN_EQUALIZER_PRESET;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.EarFunSettingsPreferenceConst.PREF_EARFUN_TRANSPARENCY_MODE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.Equalizer.TenBandEqualizerPresets;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.EarFunSettingsCustomizer;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.earfun.prefs.Equalizer;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class EarFunFreePro3SettingsCustomizer extends EarFunSettingsCustomizer {
|
||||
|
||||
@Override
|
||||
public void onPreferenceChange(Preference preference, DeviceSpecificSettingsHandler handler) {
|
||||
super.onPreferenceChange(preference, handler);
|
||||
String key = preference.getKey();
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
switch (key) {
|
||||
case PREF_EARFUN_AMBIENT_SOUND_CONTROL:
|
||||
onPreferenceChangeAmbientSoundControl(handler);
|
||||
break;
|
||||
case PREF_EARFUN_EQUALIZER_PRESET:
|
||||
onPreferenceChangeEqualizerPreset(handler, Equalizer.TenBandEqualizer, TenBandEqualizerPresets);
|
||||
break;
|
||||
}
|
||||
// if the band sliders match a preset, update the preset list
|
||||
if (Equalizer.containsKey(Equalizer.TenBandEqualizer, key)) {
|
||||
int equalizerPreset = getSelectedPresetFromEqualizerBands(handler,
|
||||
Equalizer.TenBandEqualizer, TenBandEqualizerPresets);
|
||||
ListPreference listPreferenceEqualizerPreset = handler.findPreference(PREF_EARFUN_EQUALIZER_PRESET);
|
||||
if (listPreferenceEqualizerPreset != null) {
|
||||
listPreferenceEqualizerPreset.setValue(Integer.toString(equalizerPreset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeSettings(DeviceSpecificSettingsHandler handler, Prefs prefs, String rootKey) {
|
||||
super.customizeSettings(handler, prefs, rootKey);
|
||||
initializeEqualizerPresetListPreference(handler, TenBandEqualizerPresets);
|
||||
}
|
||||
|
||||
private void onPreferenceChangeAmbientSoundControl(DeviceSpecificSettingsHandler handler) {
|
||||
ListPreference listPreferenceAmbientSound = handler.findPreference(PREF_EARFUN_AMBIENT_SOUND_CONTROL);
|
||||
ListPreference listPreferenceTransparencyMode = handler.findPreference(PREF_EARFUN_TRANSPARENCY_MODE);
|
||||
ListPreference listPreferenceAncMode = handler.findPreference(PREF_EARFUN_ANC_MODE);
|
||||
|
||||
if (listPreferenceAmbientSound == null || listPreferenceTransparencyMode == null || listPreferenceAncMode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (listPreferenceAmbientSound.getValue()) {
|
||||
case "1": // noise cancelling
|
||||
listPreferenceTransparencyMode.setVisible(false);
|
||||
listPreferenceAncMode.setVisible(true);
|
||||
break;
|
||||
case "2": // transparency
|
||||
listPreferenceTransparencyMode.setVisible(true);
|
||||
listPreferenceAncMode.setVisible(false);
|
||||
break;
|
||||
default:
|
||||
listPreferenceTransparencyMode.setVisible(false);
|
||||
listPreferenceAncMode.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public EarFunFreePro3SettingsCustomizer(final GBDevice device) {
|
||||
super(device);
|
||||
}
|
||||
}
|
||||
@@ -4171,6 +4171,18 @@
|
||||
<item>8</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="earfun_free_pro_3_audio_codec_names">
|
||||
<item>@string/pref_title_stable_connection</item>
|
||||
<item>aptX</item>
|
||||
<item>aptX Adaptive</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="earfun_free_pro_3_audio_codec_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="earfun_advanced_audio_mode_names">
|
||||
<item>Google Fast Pair</item>
|
||||
<item>LE Audio</item>
|
||||
@@ -4251,6 +4263,38 @@
|
||||
<item>13</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="earfun_free_pro_3_tap_action_names">
|
||||
<item>@string/none</item>
|
||||
<item>@string/pref_media_volumeup</item>
|
||||
<item>@string/pref_media_volumedown</item>
|
||||
<item>@string/pref_media_next</item>
|
||||
<item>@string/pref_media_previous</item>
|
||||
<item>@string/pref_media_playpause</item>
|
||||
<item>@string/prefs_game_mode</item>
|
||||
<item>@string/pref_title_touch_voice_assistant</item>
|
||||
<item>@string/earfun_tap_action_noise_control_all_modes</item>
|
||||
<item>@string/earfun_tap_action_noise_control_normal_wind</item>
|
||||
<item>@string/earfun_tap_action_noise_control_normal_ambient</item>
|
||||
<item>@string/earfun_tap_action_noise_control_wind_ambient</item>
|
||||
<item>@string/earfun_tap_action_redial</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="earfun_free_pro_3_tap_action_values">
|
||||
<item>16</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>5</item>
|
||||
<item>4</item>
|
||||
<item>1</item>
|
||||
<item>7</item>
|
||||
<item>6</item>
|
||||
<item>8</item>
|
||||
<item>9</item>
|
||||
<item>10</item>
|
||||
<item>11</item>
|
||||
<item>13</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="sony_ambient_sound_control_wind_noise_reduction_names">
|
||||
<item>@string/sony_ambient_sound_off</item>
|
||||
<item>@string/sony_ambient_sound_noise_cancelling</item>
|
||||
|
||||
@@ -2281,6 +2281,7 @@
|
||||
<string name="devicetype_bandw_pseries" translatable="false">Bowers and Wilkins P series</string>
|
||||
<string name="devicetype_earfun_air_s" translatable="false">EarFun Air S</string>
|
||||
<string name="devicetype_earfun_air_pro_4" translatable="false">EarFun Air Pro 4</string>
|
||||
<string name="devicetype_earfun_free_pro_3" translatable="false">EarFun Free Pro 3</string>
|
||||
<string name="devicetype_atc_ble_oepl" translatable="false">ATC_BLE_OEPL</string>
|
||||
<string name="devicetype_igpsport_bsc200" translatable="false">iGPSPORT BSC200</string>
|
||||
<string name="devicetype_igpsport_bsc200s" translatable="false">iGPSPORT BSC200S</string>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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:icon="@drawable/ic_videogame"
|
||||
android:key="pref_earfun_game_mode"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/earfun_low_latency_mode_hint"
|
||||
android:title="@string/earfun_low_latency_mode" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_bluetooth_searching"
|
||||
android:key="pref_earfun_connect_two_devices"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/earfun_connect_two_devices_hint"
|
||||
android:title="@string/earfun_connect_two_devices" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/earfun_free_pro_3_audio_codec_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_audio_codec_values"
|
||||
android:icon="@drawable/ic_equalizer"
|
||||
android:key="pref_earfun_audio_codec"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/audio_codec" />
|
||||
<Preference
|
||||
android:key="pref_earfun_audio_codec_hint"
|
||||
android:selectable="false"
|
||||
android:summary="@string/earfun_audio_codec_hint" />
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?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">
|
||||
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_touch"
|
||||
android:key="pref_screen_earfun_touch_options"
|
||||
android:persistent="false"
|
||||
android:title="@string/prefs_galaxy_touch_options">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_hearing"
|
||||
android:key="pref_earfun_touch_mode"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:title="@string/prefs_touch_lock_buds2" />
|
||||
|
||||
<PreferenceCategory android:title="@string/single_tap">
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:icon="@drawable/ic_filter_1"
|
||||
android:key="pref_earfun_single_tap_left_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_left" />
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:key="pref_earfun_single_tap_right_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_right" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/double_tap">
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:icon="@drawable/ic_filter_2"
|
||||
android:key="pref_earfun_double_tap_left_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_left" />
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:key="pref_earfun_double_tap_right_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_right" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/triple_tap">
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:icon="@drawable/ic_filter_3"
|
||||
android:key="pref_earfun_tripple_tap_left_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_left" />
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:key="pref_earfun_tripple_tap_right_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_right" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/long_press">
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:icon="@drawable/ic_touch"
|
||||
android:key="pref_earfun_long_tap_left_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_left" />
|
||||
<ListPreference
|
||||
android:defaultValue="16"
|
||||
android:dependency="pref_earfun_touch_mode"
|
||||
android:entries="@array/earfun_free_pro_3_tap_action_names"
|
||||
android:entryValues="@array/earfun_free_pro_3_tap_action_values"
|
||||
android:key="pref_earfun_long_tap_right_action"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/prefs_right" />
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/earfun_ambient_sound_control_names"
|
||||
android:entryValues="@array/earfun_ambient_sound_control_values"
|
||||
android:icon="@drawable/ic_hearing"
|
||||
android:key="pref_earfun_ambient_sound_control"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/pref_header_sony_ambient_sound_control" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/earfun_transparency_mode_names"
|
||||
android:entryValues="@array/earfun_transparency_mode_values"
|
||||
android:icon="@drawable/ic_hearing"
|
||||
android:key="pref_earfun_transparency_mode"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/earfun_transparency_mode" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/earfun_anc_mode_names"
|
||||
android:entryValues="@array/earfun_anc_mode_values"
|
||||
android:icon="@drawable/ic_hearing"
|
||||
android:key="pref_earfun_anc_mode"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/earfun_anc_mode" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/earfun_microphone_mode_names"
|
||||
android:entryValues="@array/earfun_microphone_mode_values"
|
||||
android:icon="@drawable/ic_microphone"
|
||||
android:key="pref_earfun_microphone_mode"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="@string/earfun_microphone_mode" />
|
||||
<Preference
|
||||
android:key="pref_earfun_microphone_mode_hint"
|
||||
android:selectable="false"
|
||||
android:summary="@string/earfun_microphone_mode_hint" />
|
||||
|
||||
<SeekBarPreference
|
||||
android:defaultValue="0"
|
||||
android:icon="@drawable/ic_volume_up"
|
||||
android:key="pref_earfun_voice_prompt_volume"
|
||||
android:max="4"
|
||||
android:title="@string/earfun_voice_prompt_volume"
|
||||
app:min="0"
|
||||
app:showSeekBarValue="true" />
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user