mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 12:56:49 +01:00
Amazfit GTR 4: Initial support
This commit is contained in:
parent
7e7019886d
commit
addf7ff6a6
@ -35,7 +35,7 @@ vendor's servers.
|
||||
- [Bip](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip)
|
||||
- [Bip Lite](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-Lite), [Bip S](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-S), [Bip U](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-U) [**\[!\]**](#special-pairing-procedures)
|
||||
- [Cor](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor), [Cor 2](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor-2)
|
||||
- [GTR](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 3](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR-3) [**\[!\]**](#special-pairing-procedures)
|
||||
- [GTR](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR), [GTR 3](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR-3), [GTR 4](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR-4) [**\[!\]**](#special-pairing-procedures)
|
||||
- [GTS](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS), [GTS 2/2e](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS), [GTS 3](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS-3) [**\[!\]**](#special-pairing-procedures)
|
||||
- [Neo](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Neo) [**\[!\]**](#special-pairing-procedures)
|
||||
- T-Rex [**\[!\]**](#special-pairing-procedures)
|
||||
|
@ -28,14 +28,12 @@ import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
import ch.qos.logback.core.FileAppender;
|
||||
import ch.qos.logback.core.encoder.Encoder;
|
||||
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
|
||||
import ch.qos.logback.core.rolling.RollingFileAppender;
|
||||
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
|
||||
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
|
||||
import ch.qos.logback.core.util.FileSize;
|
||||
import ch.qos.logback.core.util.StatusPrinter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
|
||||
public abstract class Logging {
|
||||
// Only used for tests
|
||||
@ -54,7 +52,7 @@ public abstract class Logging {
|
||||
} else {
|
||||
stopFileLogger();
|
||||
}
|
||||
getLogger().info("Gadgetbridge version: {}", BuildConfig.VERSION_NAME);
|
||||
getLogger().info("Gadgetbridge version: {}-{}", BuildConfig.VERSION_NAME, BuildConfig.GIT_HASH_SHORT);
|
||||
} catch (Exception ex) {
|
||||
Log.e("GBApplication", "External files dir not available, cannot log to file", ex);
|
||||
stopFileLogger();
|
||||
|
@ -17,17 +17,13 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_ACTIVETIME_MINUTES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_CALORIES_BURNT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_DISTANCE_METERS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GENDER;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GOAL_WEIGHT_KG;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_HEIGHT_CM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_NAME;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_SLEEP_DURATION;
|
||||
@ -36,6 +32,10 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_WEIGHT_KG;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_YEAR_OF_BIRTH;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
|
||||
public class AboutUserPreferencesActivity extends AbstractSettingsActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -47,12 +47,18 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivity {
|
||||
addPreferenceHandlerFor(PREF_USER_WEIGHT_KG);
|
||||
addPreferenceHandlerFor(PREF_USER_GENDER);
|
||||
addPreferenceHandlerFor(PREF_USER_STEPS_GOAL);
|
||||
addPreferenceHandlerFor(PREF_USER_GOAL_WEIGHT_KG);
|
||||
addPreferenceHandlerFor(PREF_USER_GOAL_STANDING_TIME_HOURS);
|
||||
addPreferenceHandlerFor(PREF_USER_GOAL_FAT_BURN_TIME_MINUTES);
|
||||
|
||||
addIntentNotificationListener(PREF_USER_STEPS_GOAL);
|
||||
addIntentNotificationListener(PREF_USER_HEIGHT_CM);
|
||||
addIntentNotificationListener(PREF_USER_SLEEP_DURATION);
|
||||
addIntentNotificationListener(PREF_USER_STEP_LENGTH_CM);
|
||||
addIntentNotificationListener(PREF_USER_DISTANCE_METERS);
|
||||
addIntentNotificationListener(PREF_USER_GOAL_WEIGHT_KG);
|
||||
addIntentNotificationListener(PREF_USER_GOAL_STANDING_TIME_HOURS);
|
||||
addIntentNotificationListener(PREF_USER_GOAL_FAT_BURN_TIME_MINUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,6 +72,10 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivity {
|
||||
PREF_USER_STEP_LENGTH_CM,
|
||||
PREF_USER_ACTIVETIME_MINUTES,
|
||||
PREF_USER_CALORIES_BURNT,
|
||||
PREF_USER_DISTANCE_METERS,};
|
||||
PREF_USER_DISTANCE_METERS,
|
||||
PREF_USER_GOAL_WEIGHT_KG,
|
||||
PREF_USER_GOAL_STANDING_TIME_HOURS,
|
||||
PREF_USER_GOAL_FAT_BURN_TIME_MINUTES
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class ConfigureReminders extends AbstractGBActivity {
|
||||
final Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
||||
int reservedSlots = prefs.getInt(DeviceSettingsPreferenceConst.PREF_RESERVER_REMINDERS_CALENDAR, coordinator.supportsCalendarEvents() ? 0 : 9);
|
||||
|
||||
int deviceSlots = coordinator.getReminderSlotCount() - reservedSlots;
|
||||
int deviceSlots = coordinator.getReminderSlotCount(gbDevice) - reservedSlots;
|
||||
|
||||
if (mGBReminderListAdapter.getItemCount() >= deviceSlots) {
|
||||
// No more free slots
|
||||
|
@ -18,7 +18,6 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@ -34,13 +33,11 @@ import android.os.Vibrator;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@ -50,18 +47,29 @@ import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||
public class FindPhoneActivity extends AbstractGBActivity {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FindPhoneActivity.class);
|
||||
|
||||
public static final String ACTION_FOUND
|
||||
= "nodomain.freeyourgadget.gadgetbridge.findphone.action.reply";
|
||||
public static final String ACTION_FOUND = "nodomain.freeyourgadget.gadgetbridge.findphone.action.reply";
|
||||
public static final String ACTION_VIBRATE = "nodomain.freeyourgadget.gadgetbridge.findphone.action.vibrate";
|
||||
public static final String ACTION_RING = "nodomain.freeyourgadget.gadgetbridge.findphone.action.ring";
|
||||
|
||||
public static final String EXTRA_RING = "extra_ring";
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action != null) {
|
||||
LOG.info("Got action: {}", action);
|
||||
|
||||
switch (action) {
|
||||
case ACTION_FOUND: {
|
||||
case ACTION_FOUND:
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case ACTION_VIBRATE:
|
||||
stopSound();
|
||||
break;
|
||||
case ACTION_RING:
|
||||
playRingtone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,8 +85,12 @@ public class FindPhoneActivity extends AbstractGBActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_find_phone);
|
||||
|
||||
final boolean ring = getIntent().getBooleanExtra(EXTRA_RING, true);
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_FOUND);
|
||||
filter.addAction(ACTION_VIBRATE);
|
||||
filter.addAction(ACTION_RING);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
|
||||
registerReceiver(mReceiver, filter); // for ACTION_FOUND
|
||||
|
||||
@ -93,7 +105,10 @@ public class FindPhoneActivity extends AbstractGBActivity {
|
||||
GB.removeNotification(GB.NOTIFICATION_ID_PHONE_FIND, this);
|
||||
|
||||
vibrate();
|
||||
playRingtone();
|
||||
if (ring) {
|
||||
playRingtone();
|
||||
}
|
||||
GBApplication.deviceService().onFindPhone(true);
|
||||
}
|
||||
|
||||
private void vibrate(){
|
||||
@ -115,7 +130,12 @@ public class FindPhoneActivity extends AbstractGBActivity {
|
||||
if (mAudioManager != null) {
|
||||
userVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
}
|
||||
mp = new MediaPlayer();
|
||||
if (mp != null && mp.isPlaying()) {
|
||||
LOG.warn("Already playing");
|
||||
return;
|
||||
} else if (mp == null) {
|
||||
mp = new MediaPlayer();
|
||||
}
|
||||
|
||||
if (!playConfiguredRingtone()) {
|
||||
playFallbackRingtone();
|
||||
@ -172,19 +192,24 @@ public class FindPhoneActivity extends AbstractGBActivity {
|
||||
}
|
||||
|
||||
private void stopSound() {
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, userVolume, AudioManager.FLAG_PLAY_SOUND);
|
||||
mp.stop();
|
||||
mp.reset();
|
||||
mp.release();
|
||||
if (mAudioManager != null) {
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, userVolume, AudioManager.FLAG_PLAY_SOUND);
|
||||
}
|
||||
if (mp != null) {
|
||||
mp.stop();
|
||||
mp.reset();
|
||||
mp.release();
|
||||
mp = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
stopVibration();
|
||||
stopSound();
|
||||
|
||||
GBApplication.deviceService().onPhoneFound();
|
||||
GBApplication.deviceService().onFindPhone(false);
|
||||
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
unregisterReceiver(mReceiver);
|
||||
|
@ -17,6 +17,25 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
|
||||
|
||||
public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_HEADER_TIME = "pref_header_time";
|
||||
public static final String PREF_HEADER_DISPLAY = "pref_header_display";
|
||||
public static final String PREF_HEADER_HEALTH = "pref_header_health";
|
||||
public static final String PREF_HEADER_WORKOUT = "pref_header_workout";
|
||||
public static final String PREF_HEADER_WORKOUT_DETECTION = "pref_header_workout_detection";
|
||||
public static final String PREF_HEADER_GPS = "pref_header_gps";
|
||||
public static final String PREF_HEADER_AGPS = "pref_header_agps";
|
||||
|
||||
public static final String PREF_SCREEN_NIGHT_MODE = "pref_screen_night_mode";
|
||||
public static final String PREF_SCREEN_SLEEP_MODE = "pref_screen_sleep_mode";
|
||||
public static final String PREF_SCREEN_LIFT_WRIST = "pref_screen_lift_wrist";
|
||||
public static final String PREF_SCREEN_PASSWORD = "pref_screen_password";
|
||||
public static final String PREF_SCREEN_ALWAYS_ON_DISPLAY = "pref_screen_always_on_display";
|
||||
public static final String PREF_SCREEN_HEARTRATE_MONITORING = "pref_screen_heartrate_monitoring";
|
||||
public static final String PREF_SCREEN_INACTIVITY_EXTENDED = "pref_screen_inactivity_extended";
|
||||
public static final String PREF_SCREEN_SOUND_AND_VIBRATION = "pref_screen_sound_and_vibration";
|
||||
public static final String PREF_SCREEN_DO_NOT_DISTURB = "pref_screen_do_not_disturb";
|
||||
public static final String PREF_SCREEN_OFFLINE_VOICE = "pref_screen_offline_voice";
|
||||
|
||||
public static final String PREF_LANGUAGE = "language";
|
||||
public static final String PREF_LANGUAGE_AUTO = "auto";
|
||||
public static final String PREF_DATEFORMAT = "dateformat";
|
||||
@ -25,9 +44,11 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_TIMEFORMAT_12H = "am/pm";
|
||||
public static final String PREF_TIMEFORMAT_AUTO = "auto";
|
||||
public static final String PREF_WEARLOCATION = "wearlocation";
|
||||
public static final String PREF_WEARDIRECTION = "weardirection";
|
||||
public static final String PREF_VIBRATION_ENABLE = "vibration_enable";
|
||||
public static final String PREF_NOTIFICATION_ENABLE = "notification_enable";
|
||||
public static final String PREF_SCREEN_BRIGHTNESS = "screen_brightness";
|
||||
public static final String PREF_SCREEN_AUTO_BRIGHTNESS = "screen_auto_brightness";
|
||||
public static final String PREF_SCREEN_ORIENTATION = "screen_orientation";
|
||||
public static final String PREF_SCREEN_TIMEOUT = "screen_timeout";
|
||||
public static final String PREF_RESERVER_ALARMS_CALENDAR = "reserve_alarms_calendar";
|
||||
@ -44,6 +65,8 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_BUTTON_1_FUNCTION_DOUBLE = "button_1_function_double";
|
||||
public static final String PREF_BUTTON_2_FUNCTION_DOUBLE = "button_2_function_double";
|
||||
public static final String PREF_BUTTON_3_FUNCTION_DOUBLE = "button_3_function_double";
|
||||
public static final String PREF_UPPER_BUTTON_LONG_PRESS = "pref_button_action_upper_long";
|
||||
public static final String PREF_LOWER_BUTTON_SHORT_PRESS = "pref_button_action_lower_short";
|
||||
public static final String PREF_VIBRATION_STRENGH_PERCENTAGE = "vibration_strength";
|
||||
public static final String PREF_RELAX_FIRMWARE_CHECKS = "relax_firmware_checks";
|
||||
|
||||
@ -80,10 +103,26 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_ALWAYS_ON_DISPLAY_AUTOMATIC = "automatic";
|
||||
public static final String PREF_ALWAYS_ON_DISPLAY_ALWAYS = "always";
|
||||
public static final String PREF_ALWAYS_ON_DISPLAY_SCHEDULED = "scheduled";
|
||||
public static final String PREF_ALWAYS_ON_DISPLAY_FOLLOW_WATCHFACE = "always_on_display_follow_watchface";
|
||||
public static final String PREF_ALWAYS_ON_DISPLAY_STYLE = "always_on_display_style";
|
||||
|
||||
public static final String PREF_VOLUME = "volume";
|
||||
public static final String PREF_CROWN_VIBRATION = "crown_vibration";
|
||||
public static final String PREF_ALERT_TONE = "alert_tone";
|
||||
public static final String PREF_COVER_TO_MUTE = "cover_to_mute";
|
||||
public static final String PREF_VIBRATE_FOR_ALERT = "vibrate_for_alert";
|
||||
public static final String PREF_TEXT_TO_SPEECH = "text_to_speech";
|
||||
|
||||
public static final String PREF_OFFLINE_VOICE_RESPOND_TURN_WRIST = "offline_voice_respond_turn_wrist";
|
||||
public static final String PREF_OFFLINE_VOICE_RESPOND_SCREEN_ON = "offline_voice_respond_screen_on";
|
||||
public static final String PREF_OFFLINE_VOICE_RESPONSE_DURING_SCREEN_LIGHTING = "offline_voice_response_during_screen_lighting";
|
||||
public static final String PREF_OFFLINE_VOICE_LANGUAGE = "offline_voice_language";
|
||||
|
||||
public static final String PREF_SLEEP_TIME = "prefs_enable_sleep_time";
|
||||
public static final String PREF_SLEEP_TIME_START = "prefs_sleep_time_start";
|
||||
public static final String PREF_SLEEP_TIME_END = "prefs_sleep_time_end";
|
||||
public static final String PREF_SLEEP_MODE_SLEEP_SCREEN = "pref_sleep_mode_sleep_screen";
|
||||
public static final String PREF_SLEEP_MODE_SMART_ENABLE = "pref_sleep_mode_smart_enable";
|
||||
|
||||
public static final String PREF_LIFTWRIST_NOSHED = "activate_display_on_lift_wrist_noshed";
|
||||
public static final String PREF_DISCONNECTNOTIF_NOSHED = "disconnect_notification_noshed";
|
||||
@ -140,6 +179,16 @@ public class DeviceSettingsPreferenceConst {
|
||||
|
||||
public static final String PREF_WORKOUT_START_ON_PHONE = "workout_start_on_phone";
|
||||
public static final String PREF_WORKOUT_SEND_GPS_TO_BAND = "workout_send_gps_to_band";
|
||||
public static final String PREF_WORKOUT_DETECTION_CATEGORIES = "workout_detection_categories";
|
||||
public static final String PREF_WORKOUT_DETECTION_ALERT = "workout_detection_alert";
|
||||
public static final String PREF_WORKOUT_DETECTION_SENSITIVITY = "workout_detection_sensitivity";
|
||||
|
||||
public static final String PREF_GPS_MODE_PRESET = "pref_gps_mode_preset";
|
||||
public static final String PREF_GPS_BAND = "pref_gps_band";
|
||||
public static final String PREF_GPS_COMBINATION = "pref_gps_combination";
|
||||
public static final String PREF_GPS_SATELLITE_SEARCH = "pref_gps_satellite_search";
|
||||
public static final String PREF_AGPS_EXPIRY_REMINDER_ENABLED = "pref_agps_expiry_reminder_enabled";
|
||||
public static final String PREF_AGPS_EXPIRY_REMINDER_TIME = "pref_agps_expiry_reminder_time";
|
||||
|
||||
public static final String PREF_FIND_PHONE = "prefs_find_phone";
|
||||
public static final String PREF_FIND_PHONE_DURATION = "prefs_find_phone_duration";
|
||||
|
@ -66,6 +66,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.XTimePreference;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.XTimePreferenceFragment;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_CONTROL_CENTER_SORTABLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_FELL_SLEEP_BROADCAST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_FELL_SLEEP_SELECTION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DEVICE_ACTION_SELECTION_BROADCAST;
|
||||
@ -360,6 +361,7 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
|
||||
addPreferenceHandlerFor(PREF_WORKOUT_ACTIVITY_TYPES_SORTABLE);
|
||||
addPreferenceHandlerFor(PREF_SHORTCUTS);
|
||||
addPreferenceHandlerFor(PREF_SHORTCUTS_SORTABLE);
|
||||
addPreferenceHandlerFor(PREF_CONTROL_CENTER_SORTABLE);
|
||||
addPreferenceHandlerFor(PREF_LANGUAGE);
|
||||
addPreferenceHandlerFor(PREF_EXPOSE_HR_THIRDPARTY);
|
||||
addPreferenceHandlerFor(PREF_BT_CONNECTED_ADVERTISEMENT);
|
||||
@ -367,9 +369,12 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
|
||||
addPreferenceHandlerFor(PREF_VIBRATION_ENABLE);
|
||||
addPreferenceHandlerFor(PREF_NOTIFICATION_ENABLE);
|
||||
addPreferenceHandlerFor(PREF_SCREEN_BRIGHTNESS);
|
||||
addPreferenceHandlerFor(PREF_SCREEN_AUTO_BRIGHTNESS);
|
||||
addPreferenceHandlerFor(PREF_SCREEN_ORIENTATION);
|
||||
addPreferenceHandlerFor(PREF_SCREEN_TIMEOUT);
|
||||
addPreferenceHandlerFor(PREF_TIMEFORMAT);
|
||||
addPreferenceHandlerFor(PREF_UPPER_BUTTON_LONG_PRESS);
|
||||
addPreferenceHandlerFor(PREF_LOWER_BUTTON_SHORT_PRESS);
|
||||
addPreferenceHandlerFor(PREF_BUTTON_1_FUNCTION_SHORT);
|
||||
addPreferenceHandlerFor(PREF_BUTTON_2_FUNCTION_SHORT);
|
||||
addPreferenceHandlerFor(PREF_BUTTON_3_FUNCTION_SHORT);
|
||||
@ -431,6 +436,9 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
|
||||
addPreferenceHandlerFor(PREF_AMPM_ENABLED);
|
||||
addPreferenceHandlerFor(PREF_SOUNDS);
|
||||
|
||||
addPreferenceHandlerFor(PREF_SLEEP_MODE_SLEEP_SCREEN);
|
||||
addPreferenceHandlerFor(PREF_SLEEP_MODE_SMART_ENABLE);
|
||||
|
||||
addPreferenceHandlerFor(PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES);
|
||||
addPreferenceHandlerFor(PREF_HYBRID_HR_FORCE_WHITE_COLOR);
|
||||
addPreferenceHandlerFor(PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES);
|
||||
@ -511,6 +519,32 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat imp
|
||||
addPreferenceHandlerFor(PREF_HOURLY_CHIME_START);
|
||||
addPreferenceHandlerFor(PREF_HOURLY_CHIME_END);
|
||||
|
||||
addPreferenceHandlerFor(PREF_WORKOUT_DETECTION_CATEGORIES);
|
||||
addPreferenceHandlerFor(PREF_WORKOUT_DETECTION_ALERT);
|
||||
addPreferenceHandlerFor(PREF_WORKOUT_DETECTION_SENSITIVITY);
|
||||
|
||||
addPreferenceHandlerFor(PREF_GPS_MODE_PRESET);
|
||||
addPreferenceHandlerFor(PREF_GPS_BAND);
|
||||
addPreferenceHandlerFor(PREF_GPS_COMBINATION);
|
||||
addPreferenceHandlerFor(PREF_GPS_SATELLITE_SEARCH);
|
||||
addPreferenceHandlerFor(PREF_AGPS_EXPIRY_REMINDER_ENABLED);
|
||||
addPreferenceHandlerFor(PREF_AGPS_EXPIRY_REMINDER_TIME);
|
||||
addPreferenceHandlerFor(PREF_ALWAYS_ON_DISPLAY_FOLLOW_WATCHFACE);
|
||||
addPreferenceHandlerFor(PREF_ALWAYS_ON_DISPLAY_STYLE);
|
||||
addPreferenceHandlerFor(PREF_WEARDIRECTION);
|
||||
|
||||
addPreferenceHandlerFor(PREF_VOLUME);
|
||||
addPreferenceHandlerFor(PREF_CROWN_VIBRATION);
|
||||
addPreferenceHandlerFor(PREF_ALERT_TONE);
|
||||
addPreferenceHandlerFor(PREF_COVER_TO_MUTE);
|
||||
addPreferenceHandlerFor(PREF_VIBRATE_FOR_ALERT);
|
||||
addPreferenceHandlerFor(PREF_TEXT_TO_SPEECH);
|
||||
|
||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_RESPOND_TURN_WRIST);
|
||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_RESPOND_SCREEN_ON);
|
||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_RESPONSE_DURING_SCREEN_LIGHTING);
|
||||
addPreferenceHandlerFor(PREF_OFFLINE_VOICE_LANGUAGE);
|
||||
|
||||
String sleepTimeState = prefs.getString(PREF_SLEEP_TIME, PREF_DO_NOT_DISTURB_OFF);
|
||||
boolean sleepTimeScheduled = sleepTimeState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);
|
||||
|
||||
|
@ -471,7 +471,7 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
|
||||
);
|
||||
|
||||
//set reminders
|
||||
holder.setRemindersView.setVisibility(coordinator.getReminderSlotCount() > 0 ? View.VISIBLE : View.GONE);
|
||||
holder.setRemindersView.setVisibility(coordinator.getReminderSlotCount(device) > 0 ? View.VISIBLE : View.GONE);
|
||||
holder.setRemindersView.setOnClickListener(new View.OnClickListener()
|
||||
|
||||
{
|
||||
|
@ -0,0 +1,45 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.capabilities;
|
||||
|
||||
public class GpsCapability {
|
||||
public enum Preset {
|
||||
ACCURACY,
|
||||
BALANCED,
|
||||
POWER_SAVING,
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
public enum Band {
|
||||
SINGLE_BAND,
|
||||
DUAL_BAND
|
||||
}
|
||||
|
||||
public enum Combination {
|
||||
LOW_POWER_GPS,
|
||||
GPS,
|
||||
GPS_BDS,
|
||||
GPS_GNOLASS,
|
||||
GPS_GALILEO,
|
||||
ALL_SATELLITES
|
||||
}
|
||||
|
||||
public enum SatelliteSearch {
|
||||
SPEED_FIRST,
|
||||
ACCURACY_FIRST
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.capabilities;
|
||||
|
||||
public class WorkoutDetectionCapability {
|
||||
public enum Category {
|
||||
WALKING,
|
||||
INDOOR_WALKING,
|
||||
OUTDOOR_RUNNING,
|
||||
TREADMILL,
|
||||
OUTDOOR_CYCLING,
|
||||
POOL_SWIMMING,
|
||||
ELLIPTICAL,
|
||||
ROWING_MACHINE
|
||||
}
|
||||
|
||||
public enum Sensitivity {
|
||||
HIGH,
|
||||
STANDARD,
|
||||
LOW
|
||||
}
|
||||
}
|
@ -624,7 +624,7 @@ public class DBHelper {
|
||||
|
||||
int reservedSlots = prefs.getInt(DeviceSettingsPreferenceConst.PREF_RESERVER_REMINDERS_CALENDAR, coordinator.supportsCalendarEvents() ? 0 : 9);
|
||||
|
||||
final int reminderSlots = coordinator.getReminderSlotCount();
|
||||
final int reminderSlots = coordinator.getReminderSlotCount(gbDevice);
|
||||
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
final DaoSession daoSession = db.getDaoSession();
|
||||
|
@ -23,6 +23,9 @@ public class GBDeviceEventFindPhone extends GBDeviceEvent {
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
START,
|
||||
STOP
|
||||
START_VIBRATE,
|
||||
STOP,
|
||||
VIBRATE,
|
||||
RING,
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,8 @@ public class GBDeviceEventUpdatePreferences extends GBDeviceEvent {
|
||||
|
||||
if (value == null) {
|
||||
editor.remove(key);
|
||||
} else if (value instanceof Short) {
|
||||
editor.putInt(key, (Short) value);
|
||||
} else if (value instanceof Integer) {
|
||||
editor.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
|
@ -250,7 +250,7 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -385,7 +385,7 @@ public interface DeviceCoordinator {
|
||||
/**
|
||||
* Indicates the maximum number of reminder slots available in the device.
|
||||
*/
|
||||
int getReminderSlotCount();
|
||||
int getReminderSlotCount(GBDevice device);
|
||||
|
||||
/**
|
||||
* Indicates the maximum number of slots available for world clocks in the device.
|
||||
|
@ -92,7 +92,7 @@ public interface EventHandler {
|
||||
|
||||
void onFindDevice(boolean start);
|
||||
|
||||
void onPhoneFound();
|
||||
void onFindPhone(boolean start);
|
||||
|
||||
void onSetConstantVibration(int integer);
|
||||
|
||||
|
@ -18,6 +18,9 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huami;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -34,6 +37,9 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuamiExtendedActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Config;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiLanguageType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType;
|
||||
|
||||
public abstract class Huami2021Coordinator extends HuamiCoordinator {
|
||||
@Override
|
||||
@ -119,23 +125,16 @@ public abstract class Huami2021Coordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
return 50;
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return getPrefs(device).getInt(Huami2021Service.REMINDERS_PREF_CAPABILITY, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedLanguageSettings(final GBDevice device) {
|
||||
return new String[]{
|
||||
"auto",
|
||||
"de_DE",
|
||||
"en_US",
|
||||
"es_ES",
|
||||
"fr_FR",
|
||||
"it_IT",
|
||||
"nl_NL",
|
||||
"pt_PT",
|
||||
"tr_TR",
|
||||
};
|
||||
// Return all known languages by default. Unsupported languages will be removed by Huami2021SettingsCustomizer
|
||||
final List<String> allLanguages = new ArrayList<>(HuamiLanguageType.idLookup.keySet());
|
||||
allLanguages.add(0, "auto");
|
||||
return allLanguages.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -145,64 +144,111 @@ public abstract class Huami2021Coordinator extends HuamiCoordinator {
|
||||
|
||||
@Override
|
||||
public List<HeartRateCapability.MeasurementInterval> getHeartRateMeasurementIntervals() {
|
||||
return Arrays.asList(
|
||||
HeartRateCapability.MeasurementInterval.OFF,
|
||||
HeartRateCapability.MeasurementInterval.SMART,
|
||||
HeartRateCapability.MeasurementInterval.MINUTES_1,
|
||||
HeartRateCapability.MeasurementInterval.MINUTES_10,
|
||||
HeartRateCapability.MeasurementInterval.MINUTES_30
|
||||
);
|
||||
// Return all known by default. Unsupported will be removed by Huami2021SettingsCustomizer
|
||||
return Arrays.asList(HeartRateCapability.MeasurementInterval.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a superset of all settings supported by Zepp OS Devices. Unsupported settings are removed
|
||||
* by {@link Huami2021SettingsCustomizer}.
|
||||
*/
|
||||
@Override
|
||||
public int[] getSupportedDeviceSpecificSettings(final GBDevice device) {
|
||||
return new int[]{
|
||||
R.xml.devicesettings_header_time,
|
||||
//R.xml.devicesettings_timeformat,
|
||||
R.xml.devicesettings_dateformat_2,
|
||||
// TODO R.xml.devicesettings_world_clocks,
|
||||
final List<Integer> settings = new ArrayList<>();
|
||||
|
||||
R.xml.devicesettings_header_display,
|
||||
R.xml.devicesettings_huami2021_displayitems,
|
||||
R.xml.devicesettings_huami2021_shortcuts,
|
||||
R.xml.devicesettings_nightmode,
|
||||
R.xml.devicesettings_liftwrist_display_sensitivity,
|
||||
R.xml.devicesettings_password,
|
||||
R.xml.devicesettings_always_on_display,
|
||||
R.xml.devicesettings_screen_timeout_5_to_15,
|
||||
R.xml.devicesettings_screen_brightness,
|
||||
//
|
||||
// Time
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_time);
|
||||
//settings.add(R.xml.devicesettings_timeformat);
|
||||
settings.add(R.xml.devicesettings_dateformat_2);
|
||||
// TODO settings.add(R.xml.devicesettings_world_clocks);
|
||||
|
||||
R.xml.devicesettings_header_health,
|
||||
R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2,
|
||||
R.xml.devicesettings_inactivity_dnd_no_threshold,
|
||||
R.xml.devicesettings_goal_notification,
|
||||
//
|
||||
// Display
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_display);
|
||||
settings.add(R.xml.devicesettings_huami2021_displayitems);
|
||||
settings.add(R.xml.devicesettings_huami2021_shortcuts);
|
||||
if (supportsControlCenter()) {
|
||||
settings.add(R.xml.devicesettings_huami2021_control_center);
|
||||
}
|
||||
settings.add(R.xml.devicesettings_nightmode);
|
||||
settings.add(R.xml.devicesettings_sleep_mode);
|
||||
settings.add(R.xml.devicesettings_liftwrist_display_sensitivity);
|
||||
settings.add(R.xml.devicesettings_password);
|
||||
settings.add(R.xml.devicesettings_always_on_display);
|
||||
settings.add(R.xml.devicesettings_screen_timeout);
|
||||
if (supportsAutoBrightness(device)) {
|
||||
settings.add(R.xml.devicesettings_screen_brightness_withauto);
|
||||
} else {
|
||||
settings.add(R.xml.devicesettings_screen_brightness);
|
||||
}
|
||||
|
||||
R.xml.devicesettings_header_workout,
|
||||
R.xml.devicesettings_workout_start_on_phone,
|
||||
R.xml.devicesettings_workout_send_gps_to_band,
|
||||
//
|
||||
// Health
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_health);
|
||||
settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
|
||||
settings.add(R.xml.devicesettings_inactivity_dnd_no_threshold);
|
||||
settings.add(R.xml.devicesettings_goal_notification);
|
||||
|
||||
R.xml.devicesettings_header_notifications,
|
||||
R.xml.devicesettings_vibrationpatterns,
|
||||
R.xml.devicesettings_donotdisturb_withauto_and_always,
|
||||
R.xml.devicesettings_screen_on_on_notifications,
|
||||
R.xml.devicesettings_autoremove_notifications,
|
||||
R.xml.devicesettings_canned_reply_16,
|
||||
R.xml.devicesettings_transliteration,
|
||||
//
|
||||
// Workout
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_workout);
|
||||
if (hasGps(device)) {
|
||||
settings.add(R.xml.devicesettings_gps_agps);
|
||||
} else {
|
||||
// If the device has GPS, it doesn't report workout start/end to the phone
|
||||
settings.add(R.xml.devicesettings_workout_start_on_phone);
|
||||
settings.add(R.xml.devicesettings_workout_send_gps_to_band);
|
||||
}
|
||||
settings.add(R.xml.devicesettings_workout_detection);
|
||||
|
||||
R.xml.devicesettings_header_calendar,
|
||||
R.xml.devicesettings_sync_calendar,
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_notifications);
|
||||
settings.add(R.xml.devicesettings_sound_and_vibration);
|
||||
settings.add(R.xml.devicesettings_vibrationpatterns);
|
||||
settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
|
||||
settings.add(R.xml.devicesettings_screen_on_on_notifications);
|
||||
settings.add(R.xml.devicesettings_autoremove_notifications);
|
||||
settings.add(R.xml.devicesettings_canned_reply_16);
|
||||
settings.add(R.xml.devicesettings_transliteration);
|
||||
|
||||
R.xml.devicesettings_header_other,
|
||||
R.xml.devicesettings_device_actions_without_not_wear,
|
||||
//
|
||||
// Calendar
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_calendar);
|
||||
settings.add(R.xml.devicesettings_sync_calendar);
|
||||
|
||||
R.xml.devicesettings_header_connection,
|
||||
R.xml.devicesettings_expose_hr_thirdparty,
|
||||
R.xml.devicesettings_bt_connected_advertisement,
|
||||
R.xml.devicesettings_high_mtu,
|
||||
//
|
||||
// Other
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_other);
|
||||
settings.add(R.xml.devicesettings_offline_voice);
|
||||
settings.add(R.xml.devicesettings_device_actions_without_not_wear);
|
||||
settings.add(R.xml.devicesettings_buttonactions_upper_long);
|
||||
settings.add(R.xml.devicesettings_buttonactions_lower_short);
|
||||
settings.add(R.xml.devicesettings_weardirection);
|
||||
|
||||
R.xml.devicesettings_header_developer,
|
||||
R.xml.devicesettings_keep_activity_data_on_device,
|
||||
};
|
||||
//
|
||||
// Connection
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_connection);
|
||||
settings.add(R.xml.devicesettings_expose_hr_thirdparty);
|
||||
settings.add(R.xml.devicesettings_bt_connected_advertisement);
|
||||
settings.add(R.xml.devicesettings_high_mtu);
|
||||
|
||||
//
|
||||
// Developer
|
||||
//
|
||||
settings.add(R.xml.devicesettings_header_developer);
|
||||
settings.add(R.xml.devicesettings_keep_activity_data_on_device);
|
||||
|
||||
return ArrayUtils.toPrimitive(settings.toArray(new Integer[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -212,13 +258,73 @@ public abstract class Huami2021Coordinator extends HuamiCoordinator {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HuamiVibrationPatternNotificationType> getVibrationPatternNotificationTypes(final GBDevice device) {
|
||||
final List<HuamiVibrationPatternNotificationType> notificationTypes = new ArrayList<>(Arrays.asList(
|
||||
HuamiVibrationPatternNotificationType.APP_ALERTS,
|
||||
HuamiVibrationPatternNotificationType.INCOMING_CALL,
|
||||
HuamiVibrationPatternNotificationType.INCOMING_SMS,
|
||||
HuamiVibrationPatternNotificationType.GOAL_NOTIFICATION,
|
||||
HuamiVibrationPatternNotificationType.ALARM,
|
||||
HuamiVibrationPatternNotificationType.IDLE_ALERTS
|
||||
));
|
||||
|
||||
if (getReminderSlotCount(device) > 0) {
|
||||
notificationTypes.add(HuamiVibrationPatternNotificationType.EVENT_REMINDER);
|
||||
}
|
||||
|
||||
if (!supportsContinuousFindDevice()) {
|
||||
notificationTypes.add(HuamiVibrationPatternNotificationType.FIND_BAND);
|
||||
}
|
||||
|
||||
if (supportsToDoList()) {
|
||||
notificationTypes.add(HuamiVibrationPatternNotificationType.SCHEDULE);
|
||||
notificationTypes.add(HuamiVibrationPatternNotificationType.TODO_LIST);
|
||||
}
|
||||
|
||||
return notificationTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
|
||||
return new Huami2021SettingsCustomizer(device);
|
||||
return new Huami2021SettingsCustomizer(device, getVibrationPatternNotificationTypes(device));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBondingStyle() {
|
||||
return BONDING_STYLE_REQUIRE_KEY;
|
||||
}
|
||||
|
||||
public boolean supportsContinuousFindDevice() {
|
||||
// TODO: Auto-detect continuous find device?
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsControlCenter() {
|
||||
// TODO: Auto-detect control center?
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsToDoList() {
|
||||
// TODO: Not yet implemented
|
||||
// TODO: When implemented, query the capability like reminders
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mainMenuHasMoreSection() {
|
||||
// Devices that have a control center don't seem to have a "more" section in the main menu
|
||||
return !supportsControlCenter();
|
||||
}
|
||||
|
||||
public boolean hasGps(final GBDevice device) {
|
||||
return supportsConfig(device, Huami2021Config.ConfigArg.WORKOUT_GPS_PRESET);
|
||||
}
|
||||
|
||||
public boolean supportsAutoBrightness(final GBDevice device) {
|
||||
return supportsConfig(device, Huami2021Config.ConfigArg.SCREEN_AUTO_BRIGHTNESS);
|
||||
}
|
||||
|
||||
private boolean supportsConfig(final GBDevice device, final Huami2021Config.ConfigArg config) {
|
||||
return Huami2021Config.deviceHasConfig(getPrefs(device), config);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public class Huami2021Service {
|
||||
public static final short CHUNKED2021_ENDPOINT_WEATHER = 0x000e;
|
||||
public static final short CHUNKED2021_ENDPOINT_ALARMS = 0x000f;
|
||||
public static final short CHUNKED2021_ENDPOINT_CANNED_MESSAGES = 0x0013;
|
||||
public static final short CHUNKED2021_ENDPOINT_CONNECTION = 0x0015;
|
||||
public static final short CHUNKED2021_ENDPOINT_USER_INFO = 0x0017;
|
||||
public static final short CHUNKED2021_ENDPOINT_STEPS = 0x0016;
|
||||
public static final short CHUNKED2021_ENDPOINT_VIBRATION_PATTERNS = 0x0018;
|
||||
@ -84,6 +85,7 @@ public class Huami2021Service {
|
||||
public static final byte DISPLAY_ITEMS_CMD_CREATE_ACK = 0x06;
|
||||
public static final byte DISPLAY_ITEMS_MENU = 0x01;
|
||||
public static final byte DISPLAY_ITEMS_SHORTCUTS = 0x02;
|
||||
public static final byte DISPLAY_ITEMS_CONTROL_CENTER = 0x03;
|
||||
public static final byte DISPLAY_ITEMS_SECTION_MAIN = 0x01;
|
||||
public static final byte DISPLAY_ITEMS_SECTION_MORE = 0x02;
|
||||
public static final byte DISPLAY_ITEMS_SECTION_DISABLED = 0x03;
|
||||
@ -91,12 +93,15 @@ public class Huami2021Service {
|
||||
/**
|
||||
* Find Device, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_FIND_DEVICE}.
|
||||
*/
|
||||
public static final byte FIND_BAND_ONESHOT = 0x03;
|
||||
public static final byte FIND_BAND_START = 0x03;
|
||||
public static final byte FIND_BAND_ACK = 0x04;
|
||||
public static final byte FIND_BAND_STOP_FROM_PHONE = 0x06;
|
||||
public static final byte FIND_BAND_STOP_FROM_BAND = 0x07;
|
||||
public static final byte FIND_PHONE_START = 0x11;
|
||||
public static final byte FIND_PHONE_ACK = 0x12;
|
||||
public static final byte FIND_PHONE_STOP_FROM_BAND = 0x13;
|
||||
public static final byte FIND_PHONE_STOP_FROM_PHONE = 0x14;
|
||||
public static final byte FIND_PHONE_MODE = 0x15;
|
||||
|
||||
/**
|
||||
* Steps, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_STEPS}.
|
||||
@ -151,6 +156,14 @@ public class Huami2021Service {
|
||||
public static final byte CANNED_MESSAGES_CMD_REPLY_SMS_CHECK = 0x0d;
|
||||
public static final byte CANNED_MESSAGES_CMD_REPLY_SMS_ALLOW = 0x0e;
|
||||
|
||||
/**
|
||||
* Connection, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_CONNECTION}.
|
||||
*/
|
||||
public static final byte CONNECTION_CMD_MTU_REQUEST = 0x01;
|
||||
public static final byte CONNECTION_CMD_MTU_RESPONSE = 0x02;
|
||||
public static final byte CONNECTION_CMD_UNKNOWN_3 = 0x03;
|
||||
public static final byte CONNECTION_CMD_UNKNOWN_4 = 0x04;
|
||||
|
||||
/**
|
||||
* Notifications, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_HEARTRATE}.
|
||||
*/
|
||||
@ -218,8 +231,6 @@ public class Huami2021Service {
|
||||
public static final byte CONFIG_CMD_RESPONSE = 0x04;
|
||||
public static final byte CONFIG_CMD_SET = 0x05;
|
||||
public static final byte CONFIG_CMD_ACK = 0x06;
|
||||
public static final byte CONFIG_REQUEST_TYPE_SPECIFIC = 0x00;
|
||||
public static final byte CONFIG_REQUEST_TYPE_ALL = 0x01; // Don't know how to parse them properly
|
||||
|
||||
/**
|
||||
* Config, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_ICONS}.
|
||||
@ -234,6 +245,8 @@ public class Huami2021Service {
|
||||
/**
|
||||
* Reminders, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_REMINDERS}.
|
||||
*/
|
||||
public static final byte REMINDERS_CMD_CAPABILITIES_REQUEST = 0x01;
|
||||
public static final byte REMINDERS_CMD_CAPABILITIES_RESPONSE = 0x02;
|
||||
public static final byte REMINDERS_CMD_REQUEST = 0x03;
|
||||
public static final byte REMINDERS_CMD_RESPONSE = 0x04;
|
||||
public static final byte REMINDERS_CMD_CREATE = 0x05;
|
||||
@ -246,6 +259,7 @@ public class Huami2021Service {
|
||||
public static final int REMINDER_FLAG_TEXT = 0x0008;
|
||||
public static final int REMINDER_FLAG_REPEAT_MONTH = 0x1000;
|
||||
public static final int REMINDER_FLAG_REPEAT_YEAR = 0x2000;
|
||||
public static final String REMINDERS_PREF_CAPABILITY = "huami_2021_capability_reminders";
|
||||
|
||||
/**
|
||||
* Calendar, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_CALENDAR}.
|
||||
|
@ -17,87 +17,405 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.text.InputType;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.MultiSelectListPreference;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.mobeta.android.dslv.DragSortListPreference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.GpsCapability;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021MenuType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Config;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.MapUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class Huami2021SettingsCustomizer extends HuamiSettingsCustomizer {
|
||||
public Huami2021SettingsCustomizer(final GBDevice device) {
|
||||
super(device);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Huami2021SettingsCustomizer.class);
|
||||
|
||||
public Huami2021SettingsCustomizer(final GBDevice device, final List<HuamiVibrationPatternNotificationType> vibrationPatternNotificationTypes) {
|
||||
super(device, vibrationPatternNotificationTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeSettings(final DeviceSpecificSettingsHandler handler, final Prefs prefs) {
|
||||
super.customizeSettings(handler, prefs);
|
||||
|
||||
setupDisplayItemsPref(
|
||||
HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE,
|
||||
HuamiConst.PREF_ALL_DISPLAY_ITEMS,
|
||||
Huami2021MenuType.displayItemNameLookup,
|
||||
handler,
|
||||
prefs
|
||||
);
|
||||
// These are not reported by the normal configs
|
||||
removeUnsupportedElementsFromListPreference(HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE, handler, prefs);
|
||||
removeUnsupportedElementsFromListPreference(HuamiConst.PREF_SHORTCUTS_SORTABLE, handler, prefs);
|
||||
removeUnsupportedElementsFromListPreference(HuamiConst.PREF_CONTROL_CENTER_SORTABLE, handler, prefs);
|
||||
|
||||
setupDisplayItemsPref(
|
||||
for (final Huami2021Config.ConfigArg config : Huami2021Config.ConfigArg.values()) {
|
||||
if (config.getPrefKey() == null) {
|
||||
continue;
|
||||
}
|
||||
switch (config.getConfigType()) {
|
||||
case BYTE:
|
||||
case BYTE_LIST:
|
||||
case STRING_LIST:
|
||||
// For list preferences, remove the unsupported items
|
||||
removeUnsupportedElementsFromListPreference(config.getPrefKey(), handler, prefs);
|
||||
break;
|
||||
case BOOL:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case DATETIME_HH_MM:
|
||||
// For other preferences, just hide them if they were not reported as supported by the device
|
||||
hidePrefIfNoConfigSupported(handler, prefs, config.getPrefKey(), config);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide all config groups that may not be mapped directly to a preference
|
||||
final Map<String, List<Huami2021Config.ConfigArg>> configScreens = new HashMap<String, List<Huami2021Config.ConfigArg>>() {{
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_NIGHT_MODE, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.NIGHT_MODE_MODE,
|
||||
Huami2021Config.ConfigArg.NIGHT_MODE_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.NIGHT_MODE_SCHEDULED_END
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_SLEEP_MODE, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.SLEEP_MODE_SLEEP_SCREEN,
|
||||
Huami2021Config.ConfigArg.SLEEP_MODE_SMART_ENABLE
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_LIFT_WRIST, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.LIFT_WRIST_MODE,
|
||||
Huami2021Config.ConfigArg.LIFT_WRIST_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.LIFT_WRIST_SCHEDULED_END,
|
||||
Huami2021Config.ConfigArg.LIFT_WRIST_RESPONSE_SENSITIVITY
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_PASSWORD, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.PASSWORD_ENABLED,
|
||||
Huami2021Config.ConfigArg.PASSWORD_TEXT
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_ALWAYS_ON_DISPLAY, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.ALWAYS_ON_DISPLAY_MODE,
|
||||
Huami2021Config.ConfigArg.ALWAYS_ON_DISPLAY_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.ALWAYS_ON_DISPLAY_SCHEDULED_END,
|
||||
Huami2021Config.ConfigArg.ALWAYS_ON_DISPLAY_FOLLOW_WATCHFACE,
|
||||
Huami2021Config.ConfigArg.ALWAYS_ON_DISPLAY_STYLE
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_AUTO_BRIGHTNESS, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.SCREEN_AUTO_BRIGHTNESS
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_HEARTRATE_MONITORING, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.HEART_RATE_ALL_DAY_MONITORING,
|
||||
Huami2021Config.ConfigArg.HEART_RATE_HIGH_ALERTS,
|
||||
Huami2021Config.ConfigArg.HEART_RATE_LOW_ALERTS,
|
||||
Huami2021Config.ConfigArg.HEART_RATE_ACTIVITY_MONITORING,
|
||||
Huami2021Config.ConfigArg.SLEEP_HIGH_ACCURACY_MONITORING,
|
||||
Huami2021Config.ConfigArg.SLEEP_BREATHING_QUALITY_MONITORING,
|
||||
Huami2021Config.ConfigArg.STRESS_MONITORING,
|
||||
Huami2021Config.ConfigArg.STRESS_RELAXATION_REMINDER,
|
||||
Huami2021Config.ConfigArg.SPO2_ALL_DAY_MONITORING,
|
||||
Huami2021Config.ConfigArg.SPO2_LOW_ALERT
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_INACTIVITY_EXTENDED, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_ENABLED,
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_SCHEDULED_END,
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_DND_ENABLED,
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_DND_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.INACTIVITY_WARNINGS_DND_SCHEDULED_END
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_HEADER_GPS, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.WORKOUT_GPS_PRESET,
|
||||
Huami2021Config.ConfigArg.WORKOUT_GPS_BAND,
|
||||
Huami2021Config.ConfigArg.WORKOUT_GPS_COMBINATION,
|
||||
Huami2021Config.ConfigArg.WORKOUT_GPS_SATELLITE_SEARCH,
|
||||
Huami2021Config.ConfigArg.WORKOUT_AGPS_EXPIRY_REMINDER_ENABLED,
|
||||
Huami2021Config.ConfigArg.WORKOUT_AGPS_EXPIRY_REMINDER_TIME
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_SOUND_AND_VIBRATION, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.VOLUME,
|
||||
Huami2021Config.ConfigArg.CROWN_VIBRATION,
|
||||
Huami2021Config.ConfigArg.ALERT_TONE,
|
||||
Huami2021Config.ConfigArg.COVER_TO_MUTE,
|
||||
Huami2021Config.ConfigArg.VIBRATE_FOR_ALERT,
|
||||
Huami2021Config.ConfigArg.TEXT_TO_SPEECH
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_DO_NOT_DISTURB, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.DND_MODE,
|
||||
Huami2021Config.ConfigArg.DND_SCHEDULED_START,
|
||||
Huami2021Config.ConfigArg.DND_SCHEDULED_END
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_HEADER_WORKOUT_DETECTION, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.WORKOUT_DETECTION_CATEGORY,
|
||||
Huami2021Config.ConfigArg.WORKOUT_DETECTION_ALERT,
|
||||
Huami2021Config.ConfigArg.WORKOUT_DETECTION_SENSITIVITY
|
||||
));
|
||||
put(DeviceSettingsPreferenceConst.PREF_SCREEN_OFFLINE_VOICE, Arrays.asList(
|
||||
Huami2021Config.ConfigArg.OFFLINE_VOICE_RESPOND_TURN_WRIST,
|
||||
Huami2021Config.ConfigArg.OFFLINE_VOICE_RESPOND_SCREEN_ON,
|
||||
Huami2021Config.ConfigArg.OFFLINE_VOICE_RESPONSE_DURING_SCREEN_LIGHTING,
|
||||
Huami2021Config.ConfigArg.OFFLINE_VOICE_LANGUAGE
|
||||
));
|
||||
}};
|
||||
|
||||
for (final Map.Entry<String, List<Huami2021Config.ConfigArg>> configScreen : configScreens.entrySet()) {
|
||||
hidePrefIfNoConfigSupported(
|
||||
handler,
|
||||
prefs,
|
||||
configScreen.getKey(),
|
||||
configScreen.getValue().toArray(new Huami2021Config.ConfigArg[0])
|
||||
);
|
||||
}
|
||||
|
||||
// Hides the headers if none of the preferences under them are available
|
||||
hidePrefIfNoneVisible(handler, DeviceSettingsPreferenceConst.PREF_HEADER_TIME, Arrays.asList(
|
||||
DeviceSettingsPreferenceConst.PREF_TIMEFORMAT,
|
||||
DeviceSettingsPreferenceConst.PREF_DATEFORMAT,
|
||||
DeviceSettingsPreferenceConst.PREF_WORLD_CLOCKS
|
||||
));
|
||||
hidePrefIfNoneVisible(handler, DeviceSettingsPreferenceConst.PREF_HEADER_DISPLAY, Arrays.asList(
|
||||
HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE,
|
||||
HuamiConst.PREF_SHORTCUTS_SORTABLE,
|
||||
HuamiConst.PREF_ALL_SHORTCUTS,
|
||||
Huami2021MenuType.shortcutsNameLookup,
|
||||
handler,
|
||||
prefs
|
||||
);
|
||||
HuamiConst.PREF_CONTROL_CENTER_SORTABLE,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_NIGHT_MODE,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_SLEEP_MODE,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_LIFT_WRIST,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_PASSWORD,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_ALWAYS_ON_DISPLAY,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_TIMEOUT,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_AUTO_BRIGHTNESS,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_BRIGHTNESS
|
||||
));
|
||||
hidePrefIfNoneVisible(handler, DeviceSettingsPreferenceConst.PREF_HEADER_HEALTH, Arrays.asList(
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_HEARTRATE_MONITORING,
|
||||
DeviceSettingsPreferenceConst.PREF_SCREEN_INACTIVITY_EXTENDED,
|
||||
DeviceSettingsPreferenceConst.PREF_USER_FITNESS_GOAL_NOTIFICATION
|
||||
));
|
||||
hidePrefIfNoneVisible(handler, DeviceSettingsPreferenceConst.PREF_HEADER_WORKOUT, Arrays.asList(
|
||||
DeviceSettingsPreferenceConst.PREF_HEADER_GPS,
|
||||
DeviceSettingsPreferenceConst.PREF_WORKOUT_START_ON_PHONE,
|
||||
DeviceSettingsPreferenceConst.PREF_WORKOUT_SEND_GPS_TO_BAND,
|
||||
DeviceSettingsPreferenceConst.PREF_HEADER_WORKOUT_DETECTION
|
||||
));
|
||||
hidePrefIfNoneVisible(handler, DeviceSettingsPreferenceConst.PREF_HEADER_AGPS, Arrays.asList(
|
||||
DeviceSettingsPreferenceConst.PREF_AGPS_EXPIRY_REMINDER_ENABLED,
|
||||
DeviceSettingsPreferenceConst.PREF_AGPS_EXPIRY_REMINDER_TIME
|
||||
));
|
||||
|
||||
setupGpsPreference(handler);
|
||||
}
|
||||
|
||||
private void setupDisplayItemsPref(final String prefKey,
|
||||
final String allItemsPrefKey,
|
||||
final Map<String, Integer> nameLookup,
|
||||
final DeviceSpecificSettingsHandler handler,
|
||||
final Prefs prefs) {
|
||||
final DragSortListPreference pref = handler.findPreference(prefKey);
|
||||
private void setupGpsPreference(final DeviceSpecificSettingsHandler handler) {
|
||||
final ListPreference prefGpsPreset = handler.findPreference(DeviceSettingsPreferenceConst.PREF_GPS_MODE_PRESET);
|
||||
final ListPreference prefGpsBand = handler.findPreference(DeviceSettingsPreferenceConst.PREF_GPS_BAND);
|
||||
final ListPreference prefGpsCombination = handler.findPreference(DeviceSettingsPreferenceConst.PREF_GPS_COMBINATION);
|
||||
final ListPreference prefGpsSatelliteSearch = handler.findPreference(DeviceSettingsPreferenceConst.PREF_GPS_SATELLITE_SEARCH);
|
||||
|
||||
if (prefGpsPreset != null) {
|
||||
// When the preset preference is changed, update the band, combination and satellite search to the corresponding values
|
||||
final Preference.OnPreferenceChangeListener onGpsPresetUpdated = (preference, newVal) -> {
|
||||
final boolean isCustomPreset = GpsCapability.Preset.CUSTOM.name().toLowerCase(Locale.ROOT).equals(newVal);
|
||||
final GpsCapability.Preset preset = GpsCapability.Preset.valueOf(newVal.toString().toUpperCase(Locale.ROOT));
|
||||
final GpsCapability.Band presetBand;
|
||||
final GpsCapability.Combination presetCombination;
|
||||
final GpsCapability.SatelliteSearch presetSatelliteSearch;
|
||||
switch (preset) {
|
||||
case ACCURACY:
|
||||
presetBand = GpsCapability.Band.DUAL_BAND;
|
||||
presetCombination = GpsCapability.Combination.ALL_SATELLITES;
|
||||
presetSatelliteSearch = GpsCapability.SatelliteSearch.ACCURACY_FIRST;
|
||||
break;
|
||||
case BALANCED:
|
||||
presetBand = GpsCapability.Band.SINGLE_BAND;
|
||||
presetCombination = GpsCapability.Combination.GPS_BDS;
|
||||
presetSatelliteSearch = GpsCapability.SatelliteSearch.ACCURACY_FIRST;
|
||||
break;
|
||||
case POWER_SAVING:
|
||||
presetBand = GpsCapability.Band.SINGLE_BAND;
|
||||
presetCombination = GpsCapability.Combination.LOW_POWER_GPS;
|
||||
presetSatelliteSearch = GpsCapability.SatelliteSearch.SPEED_FIRST;
|
||||
break;
|
||||
default:
|
||||
presetBand = null;
|
||||
presetCombination = null;
|
||||
presetSatelliteSearch = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (prefGpsBand != null) {
|
||||
prefGpsBand.setEnabled(isCustomPreset);
|
||||
if (!isCustomPreset && presetBand != null) {
|
||||
prefGpsBand.setValue(presetBand.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
if (prefGpsCombination != null) {
|
||||
prefGpsCombination.setEnabled(isCustomPreset);
|
||||
if (!isCustomPreset && presetBand != null) {
|
||||
prefGpsCombination.setValue(presetCombination.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
if (prefGpsSatelliteSearch != null) {
|
||||
prefGpsSatelliteSearch.setEnabled(isCustomPreset);
|
||||
if (!isCustomPreset && presetBand != null) {
|
||||
prefGpsSatelliteSearch.setValue(presetSatelliteSearch.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
handler.addPreferenceHandlerFor(DeviceSettingsPreferenceConst.PREF_GPS_MODE_PRESET, onGpsPresetUpdated);
|
||||
onGpsPresetUpdated.onPreferenceChange(prefGpsPreset, prefGpsPreset.getValue());
|
||||
}
|
||||
|
||||
// The gps combination can only be chosen if the gps band is single band
|
||||
if (prefGpsBand != null && prefGpsCombination != null) {
|
||||
final Preference.OnPreferenceChangeListener onGpsBandUpdate = (preference, newVal) -> {
|
||||
final boolean isSingleBand = GpsCapability.Band.SINGLE_BAND.name().toLowerCase(Locale.ROOT).equals(newVal);
|
||||
prefGpsCombination.setEnabled(isSingleBand);
|
||||
return true;
|
||||
};
|
||||
|
||||
handler.addPreferenceHandlerFor(DeviceSettingsPreferenceConst.PREF_GPS_BAND, onGpsBandUpdate);
|
||||
final boolean isCustomPreset = prefGpsPreset != null &&
|
||||
GpsCapability.Preset.CUSTOM.name().toLowerCase(Locale.ROOT).equals(prefGpsPreset.getValue());
|
||||
if (isCustomPreset) {
|
||||
onGpsBandUpdate.onPreferenceChange(prefGpsPreset, prefGpsBand.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all unsupported elements from a list preference. If they are not known, the preference
|
||||
* is hidden.
|
||||
*/
|
||||
private void removeUnsupportedElementsFromListPreference(final String prefKey,
|
||||
final DeviceSpecificSettingsHandler handler,
|
||||
final Prefs prefs) {
|
||||
final Preference pref = handler.findPreference(prefKey);
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
final List<String> allDisplayItems = prefs.getList(allItemsPrefKey, null);
|
||||
if (allDisplayItems == null || allDisplayItems.isEmpty()) {
|
||||
|
||||
// Get the list of possible values for this preference, as reported by the band
|
||||
final List<String> possibleValues = prefs.getList(Huami2021Config.getPrefPossibleValuesKey(prefKey), null);
|
||||
if (possibleValues == null || possibleValues.isEmpty()) {
|
||||
// The band hasn't reported this setting, so we don't know the possible values.
|
||||
// Hide it
|
||||
pref.setVisible(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final CharSequence[] entries = new CharSequence[allDisplayItems.size()];
|
||||
final CharSequence[] values = new CharSequence[allDisplayItems.size()];
|
||||
for (int i = 0; i < allDisplayItems.size(); i++) {
|
||||
final String screenId = allDisplayItems.get(i);
|
||||
final String screenName;
|
||||
if (screenId.equals("more")) {
|
||||
screenName = handler.getContext().getString(R.string.menuitem_more);
|
||||
} else if (nameLookup.containsKey(screenId)) {
|
||||
screenName = handler.getContext().getString(nameLookup.get(screenId));
|
||||
} else {
|
||||
screenName = handler.getContext().getString(R.string.menuitem_unknown_app, screenId);
|
||||
}
|
||||
final CharSequence[] originalEntries;
|
||||
final CharSequence[] originalValues;
|
||||
|
||||
entries[i] = screenName;
|
||||
values[i] = screenId;
|
||||
if (pref instanceof ListPreference) {
|
||||
originalEntries = ((ListPreference) pref).getEntries();
|
||||
originalValues = ((ListPreference) pref).getEntryValues();
|
||||
} else if (pref instanceof MultiSelectListPreference) {
|
||||
originalEntries = ((MultiSelectListPreference) pref).getEntries();
|
||||
originalValues = ((MultiSelectListPreference) pref).getEntryValues();
|
||||
} else {
|
||||
LOG.error("Unknown list pref class {}", pref.getClass().getName());
|
||||
return;
|
||||
}
|
||||
|
||||
pref.setEntries(entries);
|
||||
pref.setEntryValues(values);
|
||||
final List<String> prefValues = new ArrayList<>(originalValues.length);
|
||||
for (final CharSequence entryValue : originalValues) {
|
||||
prefValues.add(entryValue.toString());
|
||||
}
|
||||
|
||||
final CharSequence[] entries = new CharSequence[possibleValues.size()];
|
||||
final CharSequence[] values = new CharSequence[possibleValues.size()];
|
||||
for (int i = 0; i < possibleValues.size(); i++) {
|
||||
final String possibleValue = possibleValues.get(i);
|
||||
final int idxPrefValue = prefValues.indexOf(possibleValue);
|
||||
|
||||
if (idxPrefValue >= 0) {
|
||||
entries[i] = originalEntries[idxPrefValue];
|
||||
} else {
|
||||
entries[i] = handler.getContext().getString(R.string.menuitem_unknown_app, possibleValue);
|
||||
}
|
||||
values[i] = possibleValue;
|
||||
}
|
||||
|
||||
if (pref instanceof ListPreference) {
|
||||
((ListPreference) pref).setEntries(entries);
|
||||
((ListPreference) pref).setEntryValues(values);
|
||||
} else if (pref instanceof MultiSelectListPreference) {
|
||||
((MultiSelectListPreference) pref).setEntries(entries);
|
||||
((MultiSelectListPreference) pref).setEntryValues(values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides prefToHide if no configuration from the list has been reported by the band.
|
||||
*/
|
||||
private void hidePrefIfNoConfigSupported(final DeviceSpecificSettingsHandler handler,
|
||||
final Prefs prefs,
|
||||
final String prefToHide,
|
||||
final Huami2021Config.ConfigArg... configs) {
|
||||
final Preference pref = handler.findPreference(prefToHide);
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Huami2021Config.ConfigArg config : configs) {
|
||||
if (Huami2021Config.deviceHasConfig(prefs, config)) {
|
||||
// This preference is supported, don't hide
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// None of the configs were supported by the device, hide this preference
|
||||
pref.setVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the the prefToHide preference if none of the preferences in the preferences list are
|
||||
* visible.
|
||||
*/
|
||||
private void hidePrefIfNoneVisible(final DeviceSpecificSettingsHandler handler,
|
||||
final String prefToHide,
|
||||
final List<String> subPrefs) {
|
||||
final Preference pref = handler.findPreference(prefToHide);
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final String subPrefKey : subPrefs) {
|
||||
final Preference subPref = handler.findPreference(subPrefKey);
|
||||
if (subPref == null) {
|
||||
continue;
|
||||
}
|
||||
if (subPref.isVisible()) {
|
||||
// At least one preference is visible
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No preference was visible, hide
|
||||
pref.setVisible(false);
|
||||
}
|
||||
|
||||
public static final Creator<Huami2021SettingsCustomizer> CREATOR = new Creator<Huami2021SettingsCustomizer>() {
|
||||
@Override
|
||||
public Huami2021SettingsCustomizer createFromParcel(final Parcel in) {
|
||||
final GBDevice device = in.readParcelable(Huami2021SettingsCustomizer.class.getClassLoader());
|
||||
final List<HuamiVibrationPatternNotificationType> vibrationPatternNotificationTypes = new ArrayList<>();
|
||||
in.readList(vibrationPatternNotificationTypes, HuamiVibrationPatternNotificationType.class.getClassLoader());
|
||||
return new Huami2021SettingsCustomizer(device, vibrationPatternNotificationTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Huami2021SettingsCustomizer[] newArray(final int size) {
|
||||
return new Huami2021SettingsCustomizer[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -57,16 +57,16 @@ public class HuamiConst {
|
||||
public static final String AMAZFIT_X = "Amazfit X";
|
||||
public static final String AMAZFIT_GTS3_NAME = "Amazfit GTS 3";
|
||||
public static final String AMAZFIT_GTR3_NAME = "Amazfit GTR 3";
|
||||
public static final String AMAZFIT_GTR4_NAME = "Amazfit GTR 4";
|
||||
|
||||
public static final String XIAOMI_SMART_BAND7_NAME = "Xiaomi Smart Band 7";
|
||||
|
||||
public static final String PREF_DISPLAY_ITEMS = "display_items";
|
||||
public static final String PREF_ALL_DISPLAY_ITEMS = "all_display_items";
|
||||
public static final String PREF_DISPLAY_ITEMS_SORTABLE = "display_items_sortable";
|
||||
public static final String PREF_WORKOUT_ACTIVITY_TYPES_SORTABLE = "workout_activity_types_sortable";
|
||||
public static final String PREF_SHORTCUTS = "shortcuts";
|
||||
public static final String PREF_ALL_SHORTCUTS = "all_shortcuts";
|
||||
public static final String PREF_SHORTCUTS_SORTABLE = "shortcuts_sortable";
|
||||
public static final String PREF_CONTROL_CENTER_SORTABLE = "control_center_sortable";
|
||||
public static final String PREF_EXPOSE_HR_THIRDPARTY = "expose_hr_thirdparty";
|
||||
public static final String PREF_USE_CUSTOM_FONT = "use_custom_font";
|
||||
|
||||
@ -94,6 +94,8 @@ public class HuamiConst {
|
||||
/**
|
||||
* The suffixes match the enum {@link nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiVibrationPatternNotificationType}.
|
||||
*/
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_KEY_PREFIX = "vibration_profile_key_";
|
||||
public static final String PREF_HUAMI_DEFAULT_VIBRATION_PROFILE = "default";
|
||||
// profile
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_PREFIX = "huami_vibration_profile_";
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_APP_ALERTS = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "app_alerts";
|
||||
@ -104,6 +106,8 @@ public class HuamiConst {
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_IDLE_ALERTS = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "idle_alerts";
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "event_reminder";
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_FIND_BAND = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "find_band";
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_TODO_LIST = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "todo_list";
|
||||
public static final String PREF_HUAMI_VIBRATION_PROFILE_SCHEDULE = PREF_HUAMI_VIBRATION_PROFILE_PREFIX + "schedule";
|
||||
// count
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_PREFIX = "huami_vibration_count_";
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_APP_ALERTS = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "app_alerts";
|
||||
@ -114,6 +118,8 @@ public class HuamiConst {
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_IDLE_ALERTS = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "idle_alerts";
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_EVENT_REMINDER = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "event_reminder";
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_FIND_BAND = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "find_band";
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_TODO_LIST = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "todo_list";
|
||||
public static final String PREF_HUAMI_VIBRATION_COUNT_SCHEDULE = PREF_HUAMI_VIBRATION_COUNT_PREFIX + "schedule";
|
||||
// try
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_PREFIX = "huami_vibration_try_";
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_APP_ALERTS = PREF_HUAMI_VIBRATION_TRY_PREFIX + "app_alerts";
|
||||
@ -124,6 +130,8 @@ public class HuamiConst {
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_IDLE_ALERTS = PREF_HUAMI_VIBRATION_TRY_PREFIX + "idle_alerts";
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER = PREF_HUAMI_VIBRATION_TRY_PREFIX + "event_reminder";
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_FIND_BAND = PREF_HUAMI_VIBRATION_TRY_PREFIX + "find_band";
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_TODO_LIST = PREF_HUAMI_VIBRATION_TRY_PREFIX + "todo_list";
|
||||
public static final String PREF_HUAMI_VIBRATION_TRY_SCHEDULE = PREF_HUAMI_VIBRATION_TRY_PREFIX + "schedule";
|
||||
|
||||
public static int toActivityKind(int rawType) {
|
||||
switch (rawType) {
|
||||
|
@ -17,24 +17,23 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelUuid;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
@ -146,6 +145,10 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
return new HuamiActivitySummaryParser();
|
||||
}
|
||||
|
||||
protected static Prefs getPrefs(final GBDevice device) {
|
||||
return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()));
|
||||
}
|
||||
|
||||
public static DateTimeDisplay getDateDisplay(Context context, String deviceAddress) throws IllegalArgumentException {
|
||||
SharedPreferences sharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(deviceAddress);
|
||||
String dateFormatTime = context.getString(R.string.p_dateformat_time);
|
||||
@ -363,7 +366,8 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
return prefs.getBoolean("keep_activity_data_on_device", false);
|
||||
}
|
||||
|
||||
public static VibrationProfile getVibrationProfile(String deviceAddress, HuamiVibrationPatternNotificationType notificationType) {
|
||||
@Nullable
|
||||
public static VibrationProfile getVibrationProfile(String deviceAddress, HuamiVibrationPatternNotificationType notificationType, boolean nullOnDeviceDefault) {
|
||||
final String defaultVibrationProfileId;
|
||||
final int defaultVibrationCount;
|
||||
|
||||
@ -400,6 +404,14 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
defaultVibrationProfileId = VibrationProfile.ID_RING;
|
||||
defaultVibrationCount = 3;
|
||||
break;
|
||||
case TODO_LIST:
|
||||
defaultVibrationProfileId = VibrationProfile.ID_SHORT;
|
||||
defaultVibrationCount = 2;
|
||||
break;
|
||||
case SCHEDULE:
|
||||
defaultVibrationProfileId = VibrationProfile.ID_SHORT;
|
||||
defaultVibrationCount = 2;
|
||||
break;
|
||||
default:
|
||||
defaultVibrationProfileId = VibrationProfile.ID_MEDIUM;
|
||||
defaultVibrationCount = 2;
|
||||
@ -408,8 +420,18 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
|
||||
final String vibrationProfileId = prefs.getString(
|
||||
HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + notificationType.name().toLowerCase(Locale.ROOT),
|
||||
defaultVibrationProfileId
|
||||
HuamiConst.PREF_HUAMI_DEFAULT_VIBRATION_PROFILE
|
||||
);
|
||||
|
||||
if (HuamiConst.PREF_HUAMI_DEFAULT_VIBRATION_PROFILE.equals(vibrationProfileId)) {
|
||||
if (nullOnDeviceDefault) {
|
||||
// Return null, so the device default is used
|
||||
return null;
|
||||
}
|
||||
|
||||
return VibrationProfile.getProfile(defaultVibrationProfileId, (short) defaultVibrationCount);
|
||||
}
|
||||
|
||||
final int vibrationProfileCount = prefs.getInt(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + notificationType.name().toLowerCase(Locale.ROOT), defaultVibrationCount);
|
||||
|
||||
return VibrationProfile.getProfile(vibrationProfileId, (short) vibrationProfileCount);
|
||||
@ -423,20 +445,8 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
} else {
|
||||
prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress));
|
||||
}
|
||||
String time = prefs.getString(key, defaultValue);
|
||||
|
||||
DateFormat df = new SimpleDateFormat("HH:mm");
|
||||
try {
|
||||
return df.parse(time);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Unexpected exception in MiBand2Coordinator.getTime: " + e.getMessage());
|
||||
}
|
||||
|
||||
return new Date();
|
||||
}
|
||||
|
||||
protected static Date getTimePreference(String key, String defaultValue) {
|
||||
return getTimePreference(key, defaultValue, null);
|
||||
return prefs.getTimePreference(key, defaultValue);
|
||||
}
|
||||
|
||||
public static MiBandConst.DistanceUnit getDistanceUnit() {
|
||||
@ -501,13 +511,26 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 22; // At least, Mi Fit still allows more
|
||||
}
|
||||
|
||||
public List<HuamiVibrationPatternNotificationType> getVibrationPatternNotificationTypes(final GBDevice device) {
|
||||
return Arrays.asList(
|
||||
HuamiVibrationPatternNotificationType.APP_ALERTS,
|
||||
HuamiVibrationPatternNotificationType.INCOMING_CALL,
|
||||
HuamiVibrationPatternNotificationType.INCOMING_SMS,
|
||||
HuamiVibrationPatternNotificationType.GOAL_NOTIFICATION,
|
||||
HuamiVibrationPatternNotificationType.ALARM,
|
||||
HuamiVibrationPatternNotificationType.IDLE_ALERTS,
|
||||
HuamiVibrationPatternNotificationType.EVENT_REMINDER,
|
||||
HuamiVibrationPatternNotificationType.FIND_BAND
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
|
||||
return new HuamiSettingsCustomizer(device);
|
||||
return new HuamiSettingsCustomizer(device, getVibrationPatternNotificationTypes(device));
|
||||
}
|
||||
|
||||
public static boolean getHourlyChime(String deviceAddress) {
|
||||
|
@ -21,7 +21,9 @@ import android.text.InputType;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
@ -34,9 +36,12 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class HuamiSettingsCustomizer implements DeviceSpecificSettingsCustomizer {
|
||||
final GBDevice device;
|
||||
final List<HuamiVibrationPatternNotificationType> vibrationPatternNotificationTypes;
|
||||
|
||||
public HuamiSettingsCustomizer(final GBDevice device) {
|
||||
public HuamiSettingsCustomizer(final GBDevice device,
|
||||
final List<HuamiVibrationPatternNotificationType> vibrationPatternNotificationTypes) {
|
||||
this.device = device;
|
||||
this.vibrationPatternNotificationTypes = vibrationPatternNotificationTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,24 +51,48 @@ public class HuamiSettingsCustomizer implements DeviceSpecificSettingsCustomizer
|
||||
|
||||
@Override
|
||||
public void customizeSettings(final DeviceSpecificSettingsHandler handler, final Prefs prefs) {
|
||||
// Setup the vibration patterns for all supported notification types
|
||||
for (HuamiVibrationPatternNotificationType notificationType : HuamiVibrationPatternNotificationType.values()) {
|
||||
final String typeKey = notificationType.name().toLowerCase(Locale.ROOT);
|
||||
|
||||
// Hide unsupported notification types
|
||||
if (!vibrationPatternNotificationTypes.contains(notificationType)) {
|
||||
final String screenKey = HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_KEY_PREFIX + typeKey;
|
||||
final Preference pref = handler.findPreference(screenKey);
|
||||
if (pref != null) {
|
||||
pref.setVisible(false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
handler.addPreferenceHandlerFor(HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + typeKey);
|
||||
handler.addPreferenceHandlerFor(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey);
|
||||
handler.setInputTypeFor(HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey, InputType.TYPE_CLASS_NUMBER);
|
||||
|
||||
// Setup the try pref to vibrate the device
|
||||
final String tryPrefKey = HuamiConst.PREF_HUAMI_VIBRATION_TRY_PREFIX + typeKey;
|
||||
final Preference tryPref = handler.findPreference(tryPrefKey);
|
||||
if (tryPref != null) {
|
||||
tryPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(final Preference preference) {
|
||||
GBApplication.deviceService(device).onSendConfiguration(tryPrefKey);
|
||||
return true;
|
||||
}
|
||||
tryPref.setOnPreferenceClickListener(preference -> {
|
||||
GBApplication.deviceService(device).onSendConfiguration(tryPrefKey);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Setup the default preference - disable count if default preference is selected
|
||||
final String profilePrefKey = HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + typeKey;
|
||||
final String countPrefKey = HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX + typeKey;
|
||||
final Preference countPref = handler.findPreference(countPrefKey);
|
||||
|
||||
final Preference.OnPreferenceChangeListener profilePrefListener = (preference, newValue) -> {
|
||||
if (countPref != null) {
|
||||
countPref.setEnabled(!HuamiConst.PREF_HUAMI_DEFAULT_VIBRATION_PROFILE.equals(newValue));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
profilePrefListener.onPreferenceChange(null, prefs.getString(profilePrefKey, HuamiConst.PREF_HUAMI_DEFAULT_VIBRATION_PROFILE));
|
||||
handler.addPreferenceHandlerFor(profilePrefKey, profilePrefListener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +112,9 @@ public class HuamiSettingsCustomizer implements DeviceSpecificSettingsCustomizer
|
||||
@Override
|
||||
public HuamiSettingsCustomizer createFromParcel(final Parcel in) {
|
||||
final GBDevice device = in.readParcelable(HuamiSettingsCustomizer.class.getClassLoader());
|
||||
return new HuamiSettingsCustomizer(device);
|
||||
final List<HuamiVibrationPatternNotificationType> vibrationPatternNotificationTypes = new ArrayList<>();
|
||||
in.readList(vibrationPatternNotificationTypes, HuamiVibrationPatternNotificationType.class.getClassLoader());
|
||||
return new HuamiSettingsCustomizer(device, vibrationPatternNotificationTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,5 +131,6 @@ public class HuamiSettingsCustomizer implements DeviceSpecificSettingsCustomizer
|
||||
@Override
|
||||
public void writeToParcel(final Parcel dest, final int flags) {
|
||||
dest.writeParcelable(device, 0);
|
||||
dest.writeList(vibrationPatternNotificationTypes);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public class AmazfitBipUCoordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class AmazfitBipUProCoordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr4;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.Huami2021Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
|
||||
public class AmazfitGTR4Coordinator extends Huami2021Coordinator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR4Coordinator.class);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DeviceType getSupportedType(final GBDeviceCandidate candidate) {
|
||||
try {
|
||||
final BluetoothDevice device = candidate.getDevice();
|
||||
final String name = device.getName();
|
||||
if (name != null && name.startsWith(HuamiConst.AMAZFIT_GTR4_NAME)) {
|
||||
return DeviceType.AMAZFITGTR4;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
LOG.error("unable to check device support", e);
|
||||
}
|
||||
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceType getDeviceType() {
|
||||
return DeviceType.AMAZFITGTR4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstallHandler findInstallHandler(final Uri uri, final Context context) {
|
||||
final AmazfitGTR4FWInstallHandler handler = new AmazfitGTR4FWInstallHandler(uri, context);
|
||||
return handler.isValid() ? handler : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsContinuousFindDevice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsControlCenter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsToDoList() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr4.AmazfitGTR4FirmwareInfo;
|
||||
|
||||
public class AmazfitGTR4FWHelper extends HuamiFWHelper {
|
||||
public AmazfitGTR4FWHelper(final Uri uri, final Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxExpectedFileSize() {
|
||||
return 1024 * 1024 * 128; // 128.0MB
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void determineFirmwareInfo(final byte[] wholeFirmwareBytes) {
|
||||
firmwareInfo = new AmazfitGTR4FirmwareInfo(wholeFirmwareBytes);
|
||||
if (!firmwareInfo.isHeaderValid()) {
|
||||
throw new IllegalArgumentException("Not a Amazfit GTR 4 firmware");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
|
||||
class AmazfitGTR4FWInstallHandler extends AbstractMiBandFWInstallHandler {
|
||||
AmazfitGTR4FWInstallHandler(final Uri uri, final Context context) {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFwUpgradeNotice() {
|
||||
return mContext.getString(R.string.fw_upgrade_notice_amazfit_gtr4, helper.getHumanFirmwareVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractMiBandFWHelper createHelper(final Uri uri, final Context context) throws IOException {
|
||||
return new AmazfitGTR4FWHelper(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedDeviceType(final GBDevice device) {
|
||||
return device.getType() == DeviceType.AMAZFITGTR4;
|
||||
}
|
||||
}
|
@ -93,7 +93,7 @@ public class AmazfitNeoCoordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 0; // Neo does not support reminders
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class MiBand2Coordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ public class MiBand5Coordinator extends HuamiCoordinator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReminderSlotCount() {
|
||||
public int getReminderSlotCount(final GBDevice device) {
|
||||
return 50; // as enforced by Zepp Life
|
||||
}
|
||||
|
||||
|
@ -355,8 +355,9 @@ public class GBDeviceService implements DeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhoneFound() {
|
||||
Intent intent = createIntent().setAction(ACTION_PHONE_FOUND);
|
||||
public void onFindPhone(final boolean start) {
|
||||
Intent intent = createIntent().setAction(ACTION_PHONE_FOUND)
|
||||
.putExtra(EXTRA_FIND_START, start);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,9 @@ public class ActivityUser {
|
||||
public static final int defaultUserDistanceGoalMeters = 5000;
|
||||
public static final int defaultUserActiveTimeGoalMinutes = 60;
|
||||
public static final int defaultUserStepLengthCm = 0;
|
||||
public static final int defaultUserGoalWeightKg = 70;
|
||||
public static final int defaultUserGoalStandingTimeHours = 12;
|
||||
public static final int defaultUserFatBurnTimeMinutes = 30;
|
||||
|
||||
public static final String PREF_USER_NAME = "mi_user_alias";
|
||||
public static final String PREF_USER_YEAR_OF_BIRTH = "activity_user_year_of_birth";
|
||||
@ -70,6 +73,9 @@ public class ActivityUser {
|
||||
public static final String PREF_USER_DISTANCE_METERS = "activity_user_distance_meters";
|
||||
public static final String PREF_USER_ACTIVETIME_MINUTES = "activity_user_activetime_minutes";
|
||||
public static final String PREF_USER_STEP_LENGTH_CM = "activity_user_step_length_cm";
|
||||
public static final String PREF_USER_GOAL_WEIGHT_KG = "activity_user_goal_weight_kg";
|
||||
public static final String PREF_USER_GOAL_STANDING_TIME_HOURS = "activity_user_goal_standing_time_minutes";
|
||||
public static final String PREF_USER_GOAL_FAT_BURN_TIME_MINUTES = "activity_user_goal_fat_burn_time_minutes";
|
||||
|
||||
public ActivityUser() {
|
||||
fetchPreferences();
|
||||
|
@ -68,6 +68,7 @@ public enum DeviceType {
|
||||
MIBAND7(10041, R.drawable.ic_device_miband6, R.drawable.ic_device_miband6_disabled, R.string.devicetype_miband7),
|
||||
AMAZFITGTS3(10042, R.drawable.ic_device_amazfit_bip, R.drawable.ic_device_amazfit_bip_disabled, R.string.devicetype_amazfit_gts3),
|
||||
AMAZFITGTR3(10043, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_amazfit_gtr3),
|
||||
AMAZFITGTR4(10044, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_amazfit_gtr4),
|
||||
HPLUS(40, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_hplus),
|
||||
MAKIBESF68(41, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_makibes_f68),
|
||||
EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_exrizu_k8),
|
||||
|
@ -186,36 +186,49 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventFindPhone deviceEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got GBDeviceEventFindPhone");
|
||||
private void handleGBDeviceEvent(final GBDeviceEventFindPhone deviceEvent) {
|
||||
final Context context = getContext();
|
||||
LOG.info("Got GBDeviceEventFindPhone: {}", deviceEvent.event);
|
||||
switch (deviceEvent.event) {
|
||||
case START:
|
||||
handleGBDeviceEventFindPhoneStart();
|
||||
handleGBDeviceEventFindPhoneStart(true);
|
||||
break;
|
||||
case START_VIBRATE:
|
||||
handleGBDeviceEventFindPhoneStart(false);
|
||||
break;
|
||||
case VIBRATE:
|
||||
final Intent intentVibrate = new Intent(FindPhoneActivity.ACTION_VIBRATE);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentVibrate);
|
||||
break;
|
||||
case RING:
|
||||
final Intent intentRing = new Intent(FindPhoneActivity.ACTION_RING);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentRing);
|
||||
break;
|
||||
case STOP:
|
||||
Intent intent = new Intent(FindPhoneActivity.ACTION_FOUND);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
final Intent intentStop = new Intent(FindPhoneActivity.ACTION_FOUND);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentStop);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("unknown GBDeviceEventFindPhone");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEventFindPhoneStart() {
|
||||
private void handleGBDeviceEventFindPhoneStart(final boolean ring) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // this could be used if app in foreground // TODO: Below Q?
|
||||
Intent startIntent = new Intent(getContext(), FindPhoneActivity.class);
|
||||
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startIntent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
context.startActivity(startIntent);
|
||||
} else {
|
||||
handleGBDeviceEventFindPhoneStartNotification();
|
||||
handleGBDeviceEventFindPhoneStartNotification(ring);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
private void handleGBDeviceEventFindPhoneStartNotification() {
|
||||
private void handleGBDeviceEventFindPhoneStartNotification(final boolean ring) {
|
||||
LOG.info("Got handleGBDeviceEventFindPhoneStartNotification");
|
||||
Intent intent = new Intent(context, FindPhoneActivity.class);
|
||||
intent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
@ -303,6 +316,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
||||
}
|
||||
|
||||
savePreferencesEvent.update(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()));
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceState updateDeviceState) {
|
||||
|
@ -45,7 +45,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -54,7 +53,6 @@ import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
|
||||
@ -94,7 +92,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.language.LanguageUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.language.Transliterator;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TRANSLITERATION_LANGUAGES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ADD_CALENDAREVENT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_REORDER;
|
||||
@ -782,7 +779,8 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
break;
|
||||
}
|
||||
case ACTION_PHONE_FOUND: {
|
||||
deviceSupport.onPhoneFound();
|
||||
final boolean start = intent.getBooleanExtra(EXTRA_FIND_START, false);
|
||||
deviceSupport.onFindPhone(start);
|
||||
break;
|
||||
}
|
||||
case ACTION_SET_CONSTANT_VIBRATION: {
|
||||
|
@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr.Ama
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr2.AmazfitGTR2Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr2.AmazfitGTR2eSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr3.AmazfitGTR3Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr4.AmazfitGTR4Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts.AmazfitGTSSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts2.AmazfitGTS2MiniSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts2.AmazfitGTS2Support;
|
||||
@ -188,6 +189,8 @@ public class DeviceSupportFactory {
|
||||
return new ServiceDeviceSupport(new AmazfitGTS3Support());
|
||||
case AMAZFITGTR3:
|
||||
return new ServiceDeviceSupport(new AmazfitGTR3Support());
|
||||
case AMAZFITGTR4:
|
||||
return new ServiceDeviceSupport(new AmazfitGTR4Support());
|
||||
case MIBAND7:
|
||||
return new ServiceDeviceSupport(new MiBand7Support());
|
||||
case AMAZFITBIP:
|
||||
|
@ -303,11 +303,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhoneFound() {
|
||||
public void onFindPhone(final boolean start) {
|
||||
if (checkBusy("phone found")) {
|
||||
return;
|
||||
}
|
||||
delegate.onPhoneFound();
|
||||
delegate.onFindPhone(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -356,7 +356,7 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhoneFound() {
|
||||
public void onFindPhone(boolean start) {
|
||||
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,57 +19,91 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
|
||||
public class Huami2021MenuType {
|
||||
/**
|
||||
* These somewhat match the ones in {@link HuamiMenuType}, but not all. The band sends and
|
||||
* receives those as 8-digit upper case hex strings.
|
||||
*/
|
||||
public static final Map<String, Integer> displayItemNameLookup = new HashMap<String, Integer>() {{
|
||||
put("00000001", R.string.menuitem_personal_activity_intelligence);
|
||||
put("00000002", R.string.menuitem_hr);
|
||||
put("00000003", R.string.menuitem_workout);
|
||||
put("00000004", R.string.menuitem_weather);
|
||||
put("00000009", R.string.menuitem_alarm);
|
||||
put("0000001A", R.string.menuitem_worldclock);
|
||||
put("0000000B", R.string.menuitem_music);
|
||||
put("0000000C", R.string.menuitem_stopwatch);
|
||||
put("0000000D", R.string.menuitem_countdown);
|
||||
put("0000000E", R.string.menuitem_findphone);
|
||||
put("0000000F", R.string.menuitem_mutephone);
|
||||
put("00000013", R.string.menuitem_settings);
|
||||
put("00000014", R.string.menuitem_workout_history);
|
||||
put("00000015", R.string.menuitem_eventreminder);
|
||||
put("00000019", R.string.menuitem_pai);
|
||||
put("0000000A", R.string.menuitem_takephoto);
|
||||
put("0000001C", R.string.menuitem_stress);
|
||||
put("0000001D", R.string.menuitem_female_health);
|
||||
put("0000001E", R.string.menuitem_workout_status);
|
||||
put("00000023", R.string.menuitem_sleep);
|
||||
put("00000024", R.string.menuitem_spo2);
|
||||
put("00000026", R.string.menuitem_events);
|
||||
put("00000033", R.string.menuitem_breathing);
|
||||
put("00000038", R.string.menuitem_pomodoro);
|
||||
put("00000102", R.string.menuitem_flashlight);
|
||||
public static final Map<String, String> displayItemNameLookup = new HashMap<String, String>() {{
|
||||
put("00000001", "personal_activity_intelligence");
|
||||
put("00000002", "hr");
|
||||
put("00000003", "workout");
|
||||
put("00000004", "weather");
|
||||
put("00000009", "alarm");
|
||||
put("0000000A", "takephoto");
|
||||
put("0000000B", "music");
|
||||
put("0000000C", "stopwatch");
|
||||
put("0000000D", "countdown");
|
||||
put("0000000E", "findphone");
|
||||
put("0000000F", "mutephone");
|
||||
put("00000013", "settings");
|
||||
put("00000014", "workout_history");
|
||||
put("00000015", "eventreminder");
|
||||
put("00000016", "compass");
|
||||
put("00000019", "pai");
|
||||
put("0000001A", "worldclock");
|
||||
put("0000001C", "stress");
|
||||
put("0000001D", "female_health");
|
||||
put("0000001E", "workout_status");
|
||||
put("00000020", "calendar");
|
||||
put("00000023", "sleep");
|
||||
put("00000024", "spo2");
|
||||
put("00000025", "phone");
|
||||
put("00000026", "events");
|
||||
put("00000033", "breathing");
|
||||
put("00000038", "pomodoro");
|
||||
put("0000003E", "todo");
|
||||
put("00000041", "barometer");
|
||||
put("00000042", "voice_memos");
|
||||
put("00000044", "sun_moon");
|
||||
put("00000045", "one_tap_measuring");
|
||||
put("00000047", "membership_cards");
|
||||
put("00000100", "alexa");
|
||||
put("00000101", "offline_voice");
|
||||
put("00000102", "flashlight");
|
||||
}};
|
||||
|
||||
public static final Map<String, Integer> shortcutsNameLookup = new HashMap<String, Integer>() {{
|
||||
put("00000001", R.string.menuitem_hr);
|
||||
put("0000000A", R.string.menuitem_workout);
|
||||
put("0000000C", R.string.menuitem_workout_status);
|
||||
put("00000002", R.string.menuitem_weather);
|
||||
put("0000001A", R.string.menuitem_worldclock);
|
||||
put("00000016", R.string.menuitem_alarm);
|
||||
put("00000004", R.string.menuitem_music);
|
||||
put("00000020", R.string.menuitem_activity);
|
||||
put("00000021", R.string.menuitem_eventreminder);
|
||||
put("00000011", R.string.menuitem_female_health);
|
||||
put("00000003", R.string.menuitem_pai);
|
||||
put("0000000F", R.string.menuitem_stress);
|
||||
put("00000005", R.string.menuitem_sleep);
|
||||
put("00000013", R.string.menuitem_spo2);
|
||||
put("00000018", R.string.menuitem_events);
|
||||
put("00000012", R.string.menuitem_breathing);
|
||||
public static final Map<String, String> shortcutsNameLookup = new HashMap<String, String>() {{
|
||||
put("00000001", "hr");
|
||||
put("00000002", "weather");
|
||||
put("00000003", "pai");
|
||||
put("00000004", "music");
|
||||
put("00000005", "sleep");
|
||||
put("0000000A", "workout");
|
||||
put("0000000B", "workout_history");
|
||||
put("0000000C", "workout_status");
|
||||
put("0000000E", "one_tap_measuring");
|
||||
put("0000000F", "stress");
|
||||
put("00000011", "female_health");
|
||||
put("00000012", "breathing");
|
||||
put("00000013", "spo2");
|
||||
put("00000016", "alarm");
|
||||
put("00000017", "calendar");
|
||||
put("00000018", "events");
|
||||
put("00000019", "todo");
|
||||
put("0000001A", "worldclock");
|
||||
put("0000001B", "compass");
|
||||
put("0000001C", "barometer");
|
||||
put("0000001E", "voice_memos");
|
||||
put("00000020", "activity");
|
||||
put("00000021", "eventreminder");
|
||||
}};
|
||||
|
||||
public static final Map<String, String> controlCenterNameLookup = new HashMap<String, String>() {{
|
||||
put("00000007", "battery");
|
||||
put("00000003", "dnd");
|
||||
put("00000004", "sleep");
|
||||
put("00000008", "theater_mode");
|
||||
put("0000000D", "calendar");
|
||||
put("00000006", "volume");
|
||||
put("00000009", "screen_always_lit");
|
||||
put("00000001", "brightness");
|
||||
put("00000013", "settings");
|
||||
put("00000000", "flashlight");
|
||||
put("0000000A", "bluetooth");
|
||||
put("0000000B", "wifi");
|
||||
put("00000002", "lockscreen");
|
||||
put("00000005", "findphone");
|
||||
put("00000019", "eject_water");
|
||||
}};
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,8 +26,6 @@ import net.e175.klaus.solarpositioning.SPA;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.threeten.bp.LocalDate;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -82,11 +80,12 @@ public class Huami2021Weather {
|
||||
return new HourlyResponse();
|
||||
case "/weather/alerts":
|
||||
return new AlertsResponse();
|
||||
default:
|
||||
LOG.error("Unknown weather path {}", path);
|
||||
//case "/weather/tide":
|
||||
// return new TideResponse(weatherSpec);
|
||||
}
|
||||
|
||||
return null;
|
||||
LOG.error("Unknown weather path {}", path);
|
||||
return new Huami2021Weather.ErrorResponse(404, -2001, "Not found");
|
||||
}
|
||||
|
||||
private static class RawJsonStringResponse extends Response {
|
||||
@ -102,16 +101,23 @@ public class Huami2021Weather {
|
||||
}
|
||||
|
||||
public static class ErrorResponse extends Response {
|
||||
private final int code;
|
||||
private final int httpStatusCode;
|
||||
private final int errorCode;
|
||||
private final String message;
|
||||
|
||||
public ErrorResponse(final int code, final String message) {
|
||||
this.code = code;
|
||||
public ErrorResponse(final int httpStatusCode, final int errorCode, final String message) {
|
||||
this.httpStatusCode = httpStatusCode;
|
||||
this.errorCode = errorCode;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
@Override
|
||||
public int getHttpStatusCode() {
|
||||
return httpStatusCode;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
@ -120,6 +126,10 @@ public class Huami2021Weather {
|
||||
}
|
||||
|
||||
public static abstract class Response {
|
||||
public int getHttpStatusCode() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return GSON.toJson(this);
|
||||
}
|
||||
@ -197,8 +207,8 @@ public class Huami2021Weather {
|
||||
}
|
||||
|
||||
private static class MoonRiseSet {
|
||||
public List<String> moonPhaseValue = new ArrayList<>();
|
||||
public List<Range> moonRise = new ArrayList<>();
|
||||
public List<String> moonPhaseValue = new ArrayList<>(); // numbers? 20 21 23...
|
||||
public List<Range> moonRise = new ArrayList<>(); // yyyy-MM-dd HH:mm:ss
|
||||
}
|
||||
|
||||
private static class Range {
|
||||
@ -249,7 +259,7 @@ public class Huami2021Weather {
|
||||
// locationKey=00.000,-0.000,xiaomi_accu:000000
|
||||
public static class CurrentResponse extends Response {
|
||||
public CurrentWeatherModel currentWeatherModel;
|
||||
public Object aqiModel = new Object();
|
||||
public AqiModel aqiModel = new AqiModel();
|
||||
|
||||
public CurrentResponse(final WeatherSpec weatherSpec) {
|
||||
this.currentWeatherModel = new CurrentWeatherModel(weatherSpec);
|
||||
@ -273,11 +283,52 @@ public class Huami2021Weather {
|
||||
temperature = new UnitValue(Unit.TEMPERATURE_C, weatherSpec.currentTemp - 273);
|
||||
uvIndex = "0";
|
||||
visibility = new UnitValue(Unit.KM, "");
|
||||
weather = String.valueOf(HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode) & 0xff); // is it?
|
||||
weather = String.valueOf(HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode) & 0xff);
|
||||
wind = new Wind(weatherSpec.windDirection, Math.round(weatherSpec.windSpeed));
|
||||
}
|
||||
}
|
||||
|
||||
private static class AqiModel {
|
||||
public String pm10 = "";
|
||||
public String pm25 = "";
|
||||
}
|
||||
|
||||
// /weather/tide
|
||||
//
|
||||
// locale=en_US
|
||||
// deviceSource=7930113
|
||||
// days=10
|
||||
// isGlobal=true
|
||||
// latitude=00.000
|
||||
// longitude=-00.000
|
||||
private static class TideResponse extends Response {
|
||||
public Date pubTime;
|
||||
public String poiName; // poi tide station name
|
||||
public String poiKey; // lat,lon,POI_ID
|
||||
public List<TideDataEntry> tideData = new ArrayList<>();
|
||||
|
||||
public TideResponse(final WeatherSpec weatherSpec) {
|
||||
pubTime = new Date(weatherSpec.timestamp * 1000L);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TideDataEntry {
|
||||
public String date; // YYYY-MM-DD, but LocalDate would need API 26+
|
||||
public List<TideTableEntry> tideTable = new ArrayList<>();
|
||||
public List<TideHourlyEntry> tideHourly = new ArrayList<>();
|
||||
}
|
||||
|
||||
private static class TideTableEntry {
|
||||
public Date fxTime; // pubTime format
|
||||
public String height; // float, x.xx
|
||||
public String type; // H / L
|
||||
}
|
||||
|
||||
private static class TideHourlyEntry {
|
||||
public Date fxTime; // pubTime format
|
||||
public String height; // float, x.xx
|
||||
}
|
||||
|
||||
private enum Unit {
|
||||
PRESSURE_MB("mb"),
|
||||
PERCENTAGE("%"),
|
||||
@ -332,6 +383,7 @@ public class Huami2021Weather {
|
||||
// locationKey=00.000,-0.000,xiaomi_accu:000000
|
||||
public static class HourlyResponse extends Response {
|
||||
public Date pubTime;
|
||||
// One entry in each list per hour
|
||||
public List<String> weather;
|
||||
public List<String> temperature;
|
||||
public List<String> humidity;
|
||||
|
@ -31,6 +31,8 @@ public enum HuamiFirmwareType {
|
||||
WATCHFACE((byte) 8),
|
||||
APP((byte) 8),
|
||||
FONT_LATIN((byte) 11),
|
||||
ZEPPOS_UNKNOWN_0X13((byte) 0x13),
|
||||
ZEPPOS_APP((byte) 0xa0),
|
||||
INVALID(Byte.MIN_VALUE);
|
||||
|
||||
private final byte value;
|
||||
|
@ -52,6 +52,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashSet;
|
||||
@ -183,9 +184,7 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_HIGH_THRESHOLD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_ALERT_LOW_THRESHOLD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_SLEEP_BREATHING_QUALITY_MONITORING;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_STRESS_MONITORING;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HEARTRATE_STRESS_RELAXATION_REMINDER;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HOURLY_CHIME_ENABLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HOURLY_CHIME_END;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HOURLY_CHIME_START;
|
||||
@ -203,8 +202,6 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_ON_ON_NOTIFICATIONS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_TIMEOUT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SPO2_ALL_DAY_MONITORING;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SPO2_LOW_ALERT_THRESHOLD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SYNC_CALENDAR;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TIMEFORMAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_USER_FITNESS_GOAL_NOTIFICATION;
|
||||
@ -236,6 +233,8 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_INCOMING_CALL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_INCOMING_SMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_PREFIX;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_SCHEDULE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_COUNT_TODO_LIST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_ALARM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_APP_ALERTS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER;
|
||||
@ -245,6 +244,8 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_INCOMING_CALL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_INCOMING_SMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_SCHEDULE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_TODO_LIST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_ALARM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_APP_ALERTS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER;
|
||||
@ -254,6 +255,8 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_INCOMING_CALL;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_INCOMING_SMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_PREFIX;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_SCHEDULE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_HUAMI_VIBRATION_TRY_TODO_LIST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.COMMAND_ALARMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.COMMAND_ALARMS_WITH_TIMES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.COMMAND_GPS_VERSION;
|
||||
@ -753,21 +756,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateSleepBreathingQualityMonitoring(TransactionBuilder builder) {
|
||||
LOG.warn("setHeartrateSleepBreathingQualityMonitoring not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setSPO2AllDayMonitoring(TransactionBuilder builder) {
|
||||
LOG.warn("setSPO2AllDayMonitoring not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setSPO2AlertThreshold(TransactionBuilder builder) {
|
||||
LOG.warn("setSPO2AlertThreshold not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateStressMonitoring(TransactionBuilder builder) {
|
||||
final boolean enableHrStressMonitoring = HuamiCoordinator.getHeartrateStressMonitoring(gbDevice.getAddress());
|
||||
LOG.info("Setting heart rate stress monitoring to {}", enableHrStressMonitoring);
|
||||
@ -776,11 +764,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateStressRelaxationReminder(TransactionBuilder builder) {
|
||||
LOG.warn("setHeartrateStressRelaxationReminder not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setHeartrateMeasurementInterval(TransactionBuilder builder, int minutes) {
|
||||
if (characteristicHRControlPoint != null) {
|
||||
builder.notify(characteristicHRControlPoint, true);
|
||||
@ -998,7 +981,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
|
||||
// Delete the remaining slots, skipping the sent reminders and reserved slots
|
||||
for (int i = reminders.size() + reservedSlots; i < coordinator.getReminderSlotCount(); i++) {
|
||||
final int reminderSlotCount = coordinator.getReminderSlotCount(getDevice());
|
||||
for (int i = reminders.size() + reservedSlots; i < reminderSlotCount; i++) {
|
||||
LOG.debug("Deleting reminder at position {}", i);
|
||||
|
||||
sendReminderToDevice(builder, i, null);
|
||||
@ -1012,9 +996,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
|
||||
final DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
|
||||
final int reminderSlotCount = coordinator.getReminderSlotCount(getDevice());
|
||||
|
||||
if (position + 1 > coordinator.getReminderSlotCount()) {
|
||||
LOG.error("Reminder for position {} is over the limit of {} reminders", position, coordinator.getReminderSlotCount());
|
||||
if (position + 1 > reminderSlotCount) {
|
||||
LOG.error("Reminder for position {} is over the limit of {} reminders", position, reminderSlotCount);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1106,7 +1091,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
|
||||
try {
|
||||
baos.write(0x03);
|
||||
|
||||
|
||||
if (clocks.size() != 0) {
|
||||
baos.write(clocks.size());
|
||||
int i = 0;
|
||||
@ -1582,17 +1567,27 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
|
||||
protected int getFindDeviceInterval() {
|
||||
VibrationProfile findBand = HuamiCoordinator.getVibrationProfile(getDevice().getAddress(), HuamiVibrationPatternNotificationType.FIND_BAND);
|
||||
final VibrationProfile findBand = HuamiCoordinator.getVibrationProfile(
|
||||
getDevice().getAddress(),
|
||||
HuamiVibrationPatternNotificationType.FIND_BAND,
|
||||
supportsDeviceDefaultVibrationProfiles()
|
||||
);
|
||||
int findDeviceInterval = 0;
|
||||
|
||||
for(int len : findBand.getOnOffSequence())
|
||||
findDeviceInterval += len;
|
||||
if (findBand != null) {
|
||||
// It can be null if the device supports continuous find mode
|
||||
// If that's the case, this function shouldn't even have been called
|
||||
for(int len : findBand.getOnOffSequence())
|
||||
findDeviceInterval += len;
|
||||
|
||||
if(findBand.getRepeat() > 0)
|
||||
findDeviceInterval *= findBand.getRepeat();
|
||||
if(findBand.getRepeat() > 0)
|
||||
findDeviceInterval *= findBand.getRepeat();
|
||||
|
||||
if(findDeviceInterval > 10000) // 10 seconds, about as long as Mi Fit allows
|
||||
if(findDeviceInterval > 10000) // 10 seconds, about as long as Mi Fit allows
|
||||
findDeviceInterval = 10000;
|
||||
} else {
|
||||
findDeviceInterval = 10000;
|
||||
}
|
||||
|
||||
return findDeviceInterval;
|
||||
}
|
||||
@ -1893,18 +1888,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
case HuamiDeviceEvent.MTU_REQUEST:
|
||||
int mtu = (value[2] & 0xff) << 8 | value[1] & 0xff;
|
||||
LOG.info("device announced MTU of " + mtu);
|
||||
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
||||
if (!prefs.getBoolean(PREF_ALLOW_HIGH_MTU, false)) {
|
||||
break;
|
||||
}
|
||||
if (mtu < 23) {
|
||||
LOG.error("Device announced unreasonable low MTU of " + mtu + ", ignoring");
|
||||
break;
|
||||
}
|
||||
mMTU = mtu;
|
||||
if (huami2021ChunkedEncoder != null) {
|
||||
huami2021ChunkedEncoder.setMTU(mtu);
|
||||
}
|
||||
setMtu(mtu);
|
||||
/*
|
||||
* not really sure if this would make sense, is this event already a proof of a successful MTU
|
||||
* negotiation initiated by the Huami device, and acknowledged by the phone? do we really have to
|
||||
@ -2114,15 +2098,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
|
||||
super.onMtuChanged(gatt, mtu, status);
|
||||
|
||||
final Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
||||
|
||||
if (!prefs.getBoolean(PREF_ALLOW_HIGH_MTU, false)) {
|
||||
LOG.warn("Ignoring MTU change to {}", mtu);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("MTU changed to {}", mtu);
|
||||
this.mMTU = mtu;
|
||||
setMtu(mtu);
|
||||
}
|
||||
|
||||
protected void acknowledgeFindPhone() {
|
||||
@ -2772,22 +2749,13 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
setRotateWristToSwitchInfo(builder);
|
||||
break;
|
||||
case ActivityUser.PREF_USER_STEPS_GOAL:
|
||||
case ActivityUser.PREF_USER_CALORIES_BURNT:
|
||||
case ActivityUser.PREF_USER_SLEEP_DURATION:
|
||||
case ActivityUser.PREF_USER_GOAL_WEIGHT_KG:
|
||||
case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS:
|
||||
case ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES:
|
||||
setFitnessGoal(builder);
|
||||
break;
|
||||
case PREF_SCREEN_ON_ON_NOTIFICATIONS:
|
||||
setScreenOnOnNotification(builder);
|
||||
break;
|
||||
case PREF_SCREEN_BRIGHTNESS:
|
||||
setScreenBrightness(builder);
|
||||
break;
|
||||
case PREF_SCREEN_TIMEOUT:
|
||||
setScreenTimeout(builder);
|
||||
break;
|
||||
case PREF_ALWAYS_ON_DISPLAY_MODE:
|
||||
case PREF_ALWAYS_ON_DISPLAY_START:
|
||||
case PREF_ALWAYS_ON_DISPLAY_END:
|
||||
setAlwaysOnDisplay(builder);
|
||||
break;
|
||||
case MiBandConst.PREF_NIGHT_MODE:
|
||||
case MiBandConst.PREF_NIGHT_MODE_START:
|
||||
case MiBandConst.PREF_NIGHT_MODE_END:
|
||||
@ -2855,6 +2823,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
case PREF_HUAMI_VIBRATION_PROFILE_IDLE_ALERTS:
|
||||
case PREF_HUAMI_VIBRATION_PROFILE_EVENT_REMINDER:
|
||||
case PREF_HUAMI_VIBRATION_PROFILE_FIND_BAND:
|
||||
case PREF_HUAMI_VIBRATION_PROFILE_TODO_LIST:
|
||||
case PREF_HUAMI_VIBRATION_PROFILE_SCHEDULE:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_APP_ALERTS:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_INCOMING_CALL:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_INCOMING_SMS:
|
||||
@ -2863,6 +2833,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
case PREF_HUAMI_VIBRATION_COUNT_IDLE_ALERTS:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_EVENT_REMINDER:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_FIND_BAND:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_TODO_LIST:
|
||||
case PREF_HUAMI_VIBRATION_COUNT_SCHEDULE:
|
||||
case PREF_HUAMI_VIBRATION_TRY_APP_ALERTS:
|
||||
case PREF_HUAMI_VIBRATION_TRY_INCOMING_CALL:
|
||||
case PREF_HUAMI_VIBRATION_TRY_INCOMING_SMS:
|
||||
@ -2871,6 +2843,8 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
case PREF_HUAMI_VIBRATION_TRY_IDLE_ALERTS:
|
||||
case PREF_HUAMI_VIBRATION_TRY_EVENT_REMINDER:
|
||||
case PREF_HUAMI_VIBRATION_TRY_FIND_BAND:
|
||||
case PREF_HUAMI_VIBRATION_TRY_TODO_LIST:
|
||||
case PREF_HUAMI_VIBRATION_TRY_SCHEDULE:
|
||||
setVibrationPattern(builder, config);
|
||||
break;
|
||||
case PREF_HEARTRATE_ACTIVITY_MONITORING:
|
||||
@ -2881,21 +2855,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
case PREF_HEARTRATE_ALERT_LOW_THRESHOLD:
|
||||
setHeartrateAlert(builder);
|
||||
break;
|
||||
case PREF_HEARTRATE_SLEEP_BREATHING_QUALITY_MONITORING:
|
||||
setHeartrateSleepBreathingQualityMonitoring(builder);
|
||||
break;
|
||||
case PREF_SPO2_ALL_DAY_MONITORING:
|
||||
setSPO2AllDayMonitoring(builder);
|
||||
break;
|
||||
case PREF_SPO2_LOW_ALERT_THRESHOLD:
|
||||
setSPO2AlertThreshold(builder);
|
||||
break;
|
||||
case PREF_HEARTRATE_STRESS_MONITORING:
|
||||
setHeartrateStressMonitoring(builder);
|
||||
break;
|
||||
case PREF_HEARTRATE_STRESS_RELAXATION_REMINDER:
|
||||
setHeartrateStressRelaxationReminder(builder);
|
||||
break;
|
||||
case PasswordCapabilityImpl.PREF_PASSWORD:
|
||||
case PasswordCapabilityImpl.PREF_PASSWORD_ENABLED:
|
||||
setPassword(builder);
|
||||
@ -2933,13 +2895,24 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
final HuamiVibrationPatternNotificationType notificationType = HuamiVibrationPatternNotificationType.valueOf(notificationTypeName);
|
||||
final boolean isTry = preferenceKey.startsWith(PREF_HUAMI_VIBRATION_TRY_PREFIX);
|
||||
|
||||
final VibrationProfile vibrationProfile = HuamiCoordinator.getVibrationProfile(getDevice().getAddress(), notificationType);
|
||||
final VibrationProfile vibrationProfile = HuamiCoordinator.getVibrationProfile(
|
||||
getDevice().getAddress(),
|
||||
notificationType,
|
||||
supportsDeviceDefaultVibrationProfiles()
|
||||
);
|
||||
|
||||
setVibrationPattern(builder, notificationType, isTry, vibrationProfile);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the device supports built-in default vibration profiles.
|
||||
*/
|
||||
protected boolean supportsDeviceDefaultVibrationProfiles() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test or set a {@link VibrationProfile}.
|
||||
*
|
||||
@ -2949,9 +2922,14 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
* @param profile the {@link VibrationProfile}
|
||||
*/
|
||||
protected void setVibrationPattern(final TransactionBuilder builder,
|
||||
final HuamiVibrationPatternNotificationType notificationType,
|
||||
final boolean test,
|
||||
final VibrationProfile profile) {
|
||||
final HuamiVibrationPatternNotificationType notificationType,
|
||||
final boolean test,
|
||||
final VibrationProfile profile) {
|
||||
if (profile == null) {
|
||||
LOG.error("Vibration profile is null for {}", notificationType);
|
||||
return;
|
||||
}
|
||||
|
||||
final int MAX_TOTAL_LENGTH_MS = 10_000; // 10 seconds, about as long as Mi Fit allows
|
||||
|
||||
// The on-off sequence, until the max total length is reached
|
||||
@ -2977,6 +2955,10 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
|
||||
protected List<Short> truncateVibrationsOnOff(final VibrationProfile profile, final int limitMillis) {
|
||||
if (profile == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
int totalLengthMs = 0;
|
||||
|
||||
// The on-off sequence, until the max total length is reached
|
||||
@ -3304,11 +3286,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setAlwaysOnDisplay(TransactionBuilder builder) {
|
||||
LOG.warn("Always on display not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setActivateDisplayOnLiftWrist(TransactionBuilder builder) {
|
||||
ActivateDisplayOnLift displayOnLift = HuamiCoordinator.getActivateDisplayOnLiftWrist(getContext(), gbDevice.getAddress());
|
||||
LOG.info("Setting activate display on lift wrist to " + displayOnLift);
|
||||
@ -3812,24 +3789,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setScreenOnOnNotification(TransactionBuilder builder) {
|
||||
LOG.warn("Function not implemented");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setScreenBrightness(TransactionBuilder builder) {
|
||||
LOG.warn("Function not implemented");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setScreenTimeout(TransactionBuilder builder) {
|
||||
LOG.warn("Function not implemented");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport setLanguage(TransactionBuilder builder) {
|
||||
String localeString = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getString("language", "auto");
|
||||
if (localeString == null || localeString.equals("auto")) {
|
||||
@ -3978,10 +3937,18 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeToChunked2021(TransactionBuilder builder, short type, byte data, boolean encrypt) {
|
||||
writeToChunked2021(builder, type, new byte[]{data}, encrypt);
|
||||
}
|
||||
|
||||
protected void writeToChunked2021(TransactionBuilder builder, short type, byte[] data, boolean encrypt) {
|
||||
huami2021ChunkedEncoder.write(builder, type, data, force2021Protocol(), encrypt);
|
||||
}
|
||||
|
||||
protected void writeToChunked2021(final String taskName, short type, byte data, boolean encrypt) {
|
||||
writeToChunked2021(taskName, type, new byte[]{data}, encrypt);
|
||||
}
|
||||
|
||||
protected void writeToChunked2021(final String taskName, short type, byte[] data, boolean encrypt) {
|
||||
try {
|
||||
final TransactionBuilder builder = performInitialized(taskName);
|
||||
@ -4020,11 +3987,6 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return this;
|
||||
}
|
||||
|
||||
protected HuamiSupport requestShortcuts(TransactionBuilder builder) {
|
||||
LOG.warn("Function not implemented");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String customStringFilter(String inputString) {
|
||||
if (HuamiCoordinator.getUseCustomFont(gbDevice.getAddress())) {
|
||||
@ -4066,7 +4028,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
}
|
||||
|
||||
public void phase3Initialize(TransactionBuilder builder) {
|
||||
final DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
|
||||
final HuamiCoordinator coordinator = getCoordinator();
|
||||
|
||||
LOG.info("phase3Initialize...");
|
||||
|
||||
@ -4094,7 +4056,7 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
setHeartrateMeasurementInterval(builder, HuamiCoordinator.getHeartRateMeasurementInterval(getDevice().getAddress()));
|
||||
sendReminders(builder);
|
||||
setWorldClocks(builder);
|
||||
for (final HuamiVibrationPatternNotificationType type : HuamiVibrationPatternNotificationType.values()) {
|
||||
for (final HuamiVibrationPatternNotificationType type : coordinator.getVibrationPatternNotificationTypes(getDevice())) {
|
||||
final String typeKey = type.name().toLowerCase(Locale.ROOT);
|
||||
setVibrationPattern(builder, HuamiConst.PREF_HUAMI_VIBRATION_PROFILE_PREFIX + typeKey);
|
||||
}
|
||||
@ -4116,6 +4078,24 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return mMTU;
|
||||
}
|
||||
|
||||
protected void setMtu(final int mtu) {
|
||||
final Prefs prefs = getDevicePrefs();
|
||||
if (!prefs.getBoolean(PREF_ALLOW_HIGH_MTU, false)) {
|
||||
LOG.warn("High MTU is not allowed, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtu < 23) {
|
||||
LOG.error("Device announced unreasonable low MTU of {}, ignoring", mtu);
|
||||
return;
|
||||
}
|
||||
|
||||
this.mMTU = mtu;
|
||||
if (huami2021ChunkedEncoder != null) {
|
||||
huami2021ChunkedEncoder.setMTU(mtu);
|
||||
}
|
||||
}
|
||||
|
||||
public int getActivitySampleSize() {
|
||||
return mActivitySampleSize;
|
||||
}
|
||||
@ -4124,6 +4104,14 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements
|
||||
return GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean("force_new_protocol", false);
|
||||
}
|
||||
|
||||
protected HuamiCoordinator getCoordinator() {
|
||||
return (HuamiCoordinator) DeviceHelper.getInstance().getCoordinator(gbDevice);
|
||||
}
|
||||
|
||||
protected Prefs getDevicePrefs() {
|
||||
return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle2021Payload(int type, byte[] payload) {
|
||||
if (type == Huami2021Service.CHUNKED2021_ENDPOINT_COMPAT) {
|
||||
|
@ -28,7 +28,10 @@ public enum HuamiVibrationPatternNotificationType {
|
||||
ALARM(0x05),
|
||||
IDLE_ALERTS(0x06),
|
||||
EVENT_REMINDER(0x08),
|
||||
FIND_BAND(0x09);
|
||||
FIND_BAND(0x09),
|
||||
TODO_LIST(0x0a),
|
||||
SCHEDULE(0x0c),
|
||||
;
|
||||
|
||||
private final byte code;
|
||||
|
||||
|
@ -24,7 +24,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3.AmazfitGTR3FWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Support;
|
||||
|
@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr4;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021FirmwareInfo;
|
||||
|
||||
public class AmazfitGTR4FirmwareInfo extends Huami2021FirmwareInfo {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR4FirmwareInfo.class);
|
||||
|
||||
private static final Map<Integer, String> crcToVersion = new HashMap<Integer, String>() {{
|
||||
// firmware
|
||||
}};
|
||||
|
||||
public AmazfitGTR4FirmwareInfo(final byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceName() {
|
||||
return HuamiConst.AMAZFIT_GTR4_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getExpectedFirmwareHeader() {
|
||||
return new byte[]{(byte) 0x51, (byte) 0x71, (byte) 0x9c}; // Probably bogus, only checked against 1 firmware files
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerallyCompatibleWith(final GBDevice device) {
|
||||
return isHeaderValid() && device.getType() == DeviceType.AMAZFITGTR4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Integer, String> getCrcMap() {
|
||||
return crcToVersion;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/* Copyright (C) 2022 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr4.AmazfitGTR4FWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.Huami2021Support;
|
||||
|
||||
public class AmazfitGTR4Support extends Huami2021Support {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AmazfitGTR4Support.class);
|
||||
|
||||
@Override
|
||||
public HuamiFWHelper createFWHelper(final Uri uri, final Context context) throws IOException {
|
||||
return new AmazfitGTR4FWHelper(uri, context);
|
||||
}
|
||||
}
|
@ -209,8 +209,8 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhoneFound() {
|
||||
byte[] bytes = gbDeviceProtocol.encodePhoneFound();
|
||||
public void onFindPhone(boolean start) {
|
||||
byte[] bytes = gbDeviceProtocol.encodeFindPhone(start);
|
||||
sendToDevice(bytes);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ public abstract class GBDeviceProtocol {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] encodePhoneFound() {
|
||||
public byte[] encodeFindPhone(boolean start) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband6.MiBand6Coordin
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband7.MiBand7Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts3.AmazfitGTS3Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr3.AmazfitGTR3Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr4.AmazfitGTR4Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppe.ZeppECoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr2.AmazfitGTR2eCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSCoordinator;
|
||||
@ -293,6 +294,7 @@ public class DeviceHelper {
|
||||
result.add(new MiBand7Coordinator());
|
||||
result.add(new AmazfitGTS3Coordinator());
|
||||
result.add(new AmazfitGTR3Coordinator());
|
||||
result.add(new AmazfitGTR4Coordinator());
|
||||
result.add(new MiBand2HRXCoordinator());
|
||||
result.add(new MiBand2Coordinator()); // Note: MiBand2 and all of the above must come before MiBand because detection is hacky, atm
|
||||
result.add(new MiBandCoordinator());
|
||||
|
@ -19,9 +19,13 @@ package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -169,10 +173,27 @@ public class Prefs {
|
||||
return Arrays.asList(stringValue.split(","));
|
||||
}
|
||||
|
||||
public Date getTimePreference(final String key, final String defaultValue) {
|
||||
final String time = getString(key, defaultValue);
|
||||
|
||||
final DateFormat df = new SimpleDateFormat("HH:mm", Locale.ROOT);
|
||||
try {
|
||||
return df.parse(time);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Error reading datetime preference value: " + key + "; returning default current time", e); // log the first exception
|
||||
}
|
||||
|
||||
return new Date();
|
||||
}
|
||||
|
||||
private void logReadError(String key, Exception ex) {
|
||||
Log.e(TAG, "Error reading preference value: " + key + "; returning default value", ex); // log the first exception
|
||||
}
|
||||
|
||||
public boolean contains(final String key) {
|
||||
return preferences.contains(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the underlying SharedPreferences, typically only used for editing values.
|
||||
* @return the underlying SharedPreferences object.
|
||||
|
@ -18,6 +18,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -147,6 +148,23 @@ public class StringUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String untilNullTerminator(final ByteBuffer buf) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
while (buf.position() < buf.limit()) {
|
||||
final byte b = buf.get();
|
||||
|
||||
if (b == 0) {
|
||||
return baos.toString();
|
||||
}
|
||||
|
||||
baos.write(b);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] array) {
|
||||
return GB.hexdump(array, 0, -1);
|
||||
}
|
||||
|
5
app/src/main/res/drawable/ic_checklist.xml
Normal file
5
app/src/main/res/drawable/ic_checklist.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#7E7E7E"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M22,7h-9v2h9V7zM22,15h-9v2h9V15zM5.54,11L2,7.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,11zM5.54,19L2,15.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,19z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_volume_off.xml
Normal file
5
app/src/main/res/drawable/ic_volume_off.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#7E7E7E"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/>
|
||||
</vector>
|
@ -146,6 +146,15 @@
|
||||
<item>right</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="weardirection">
|
||||
<item>@string/buttons_on_left</item>
|
||||
<item>@string/buttons_on_right</item>
|
||||
</string-array>
|
||||
<string-array name="weardirection_values">
|
||||
<item>buttons_on_left</item>
|
||||
<item>buttons_on_right</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="orientation">
|
||||
<item>@string/horizontal</item>
|
||||
<item>@string/vertical</item>
|
||||
@ -156,6 +165,7 @@
|
||||
</string-array>
|
||||
|
||||
<string-array name="vibration_profile">
|
||||
<item>@string/vibration_profile_default</item>
|
||||
<item>@string/vibration_profile_staccato</item>
|
||||
<item>@string/vibration_profile_short</item>
|
||||
<item>@string/vibration_profile_medium</item>
|
||||
@ -165,6 +175,8 @@
|
||||
<item>@string/vibration_profile_alarm_clock</item>
|
||||
</string-array>
|
||||
<string-array name="vibration_profile_values">
|
||||
<!-- special case - default -->
|
||||
<item>@string/p_default</item>
|
||||
<!-- Note: corresponds with IDs in VibrationProfile -->
|
||||
<item>@string/p_staccato</item>
|
||||
<item>@string/p_short</item>
|
||||
@ -624,12 +636,208 @@
|
||||
<item>@string/p_menuitem_music</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_huami2021_display_items">
|
||||
<string-array name="pref_huami2021_empty_array">
|
||||
<!-- empty array, will be requested from band -->
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_huami2021_shortcuts">
|
||||
<!-- empty array, will be requested from band -->
|
||||
<string-array name="pref_workout_detection_categories">
|
||||
<item>@string/activity_type_walking</item>
|
||||
<item>@string/activity_type_indoor_walking</item>
|
||||
<item>@string/activity_type_outdoor_running</item>
|
||||
<item>@string/activity_type_treadmill</item>
|
||||
<item>@string/activity_type_outdoor_cycling</item>
|
||||
<item>@string/activity_type_pool_swimming</item>
|
||||
<item>@string/activity_type_elliptical</item>
|
||||
<item>@string/activity_type_rowing_machine</item>
|
||||
</string-array>
|
||||
<string-array name="pref_workout_detection_categories_values">
|
||||
<item>walking</item>
|
||||
<item>indoor_walking</item>
|
||||
<item>outdoor_running</item>
|
||||
<item>treadmill</item>
|
||||
<item>outdoor_cycling</item>
|
||||
<item>pool_swimming</item>
|
||||
<item>elliptical</item>
|
||||
<item>rowing_machine</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_gps_mode_preset">
|
||||
<item>@string/accuracy</item>
|
||||
<item>@string/balanced</item>
|
||||
<item>@string/power_saving</item>
|
||||
<item>@string/custom</item>
|
||||
</string-array>
|
||||
<string-array name="pref_gps_mode_preset_values">
|
||||
<item>accuracy</item>
|
||||
<item>balanced</item>
|
||||
<item>power_saving</item>
|
||||
<item>custom</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_gps_band">
|
||||
<item>@string/single_band</item>
|
||||
<item>@string/dual_band</item>
|
||||
</string-array>
|
||||
<string-array name="pref_gps_band_values">
|
||||
<item>single_band</item>
|
||||
<item>dual_band</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_gps_combination">
|
||||
<item>@string/low_power_gps</item>
|
||||
<item>@string/gps</item>
|
||||
<item>@string/gps_bds</item>
|
||||
<item>@string/gps_gnolass</item>
|
||||
<item>@string/gps_galileo</item>
|
||||
<item>@string/all_satellites</item>
|
||||
</string-array>
|
||||
<string-array name="pref_gps_combination_values">
|
||||
<item>low_power_gps</item>
|
||||
<item>gps</item>
|
||||
<item>gps_bds</item>
|
||||
<item>gps_gnolass</item>
|
||||
<item>gps_galileo</item>
|
||||
<item>all_satellites</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_gps_satellite_search">
|
||||
<item>@string/speed_first</item>
|
||||
<item>@string/accuracy_first</item>
|
||||
</string-array>
|
||||
<string-array name="pref_gps_satellite_search_values">
|
||||
<item>speed_first</item>
|
||||
<item>accuracy_first</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="workout_detection_sensitivity">
|
||||
<item>@string/sony_speak_to_chat_sensitivity_high</item>
|
||||
<item>@string/sony_speak_to_chat_sensitivity_standard</item>
|
||||
<item>@string/sony_speak_to_chat_sensitivity_low</item>
|
||||
</string-array>
|
||||
<string-array name="workout_detection_sensitivity_values">
|
||||
<item>high</item>
|
||||
<item>standard</item>
|
||||
<item>low</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_zepp_os_apps">
|
||||
<item>@string/menuitem_activity</item>
|
||||
<item>@string/menuitem_alarm</item>
|
||||
<item>@string/menuitem_alexa</item>
|
||||
<item>@string/menuitem_barometer</item>
|
||||
<item>@string/menuitem_breathing</item>
|
||||
<item>@string/menuitem_calendar</item>
|
||||
<item>@string/menuitem_compass</item>
|
||||
<item>@string/menuitem_countdown</item>
|
||||
<item>@string/menuitem_eventreminder</item>
|
||||
<item>@string/menuitem_events</item>
|
||||
<item>@string/menuitem_female_health</item>
|
||||
<item>@string/menuitem_findphone</item>
|
||||
<item>@string/menuitem_flashlight</item>
|
||||
<item>@string/menuitem_hr</item>
|
||||
<item>@string/menuitem_membership_cards</item>
|
||||
<item>@string/menuitem_music</item>
|
||||
<item>@string/menuitem_mutephone</item>
|
||||
<item>@string/menuitem_offline_voice</item>
|
||||
<item>@string/menuitem_one_tap_measuring</item>
|
||||
<item>@string/menuitem_pai</item>
|
||||
<item>@string/menuitem_personal_activity_intelligence</item>
|
||||
<item>@string/menuitem_phone</item>
|
||||
<item>@string/menuitem_pomodoro</item>
|
||||
<item>@string/menuitem_settings</item>
|
||||
<item>@string/menuitem_sleep</item>
|
||||
<item>@string/menuitem_spo2</item>
|
||||
<item>@string/menuitem_stopwatch</item>
|
||||
<item>@string/menuitem_stress</item>
|
||||
<item>@string/menuitem_sun_moon</item>
|
||||
<item>@string/menuitem_takephoto</item>
|
||||
<item>@string/menuitem_todo</item>
|
||||
<item>@string/menuitem_voice_memos</item>
|
||||
<item>@string/menuitem_weather</item>
|
||||
<item>@string/menuitem_workout_history</item>
|
||||
<item>@string/menuitem_workout</item>
|
||||
<item>@string/menuitem_workout_status</item>
|
||||
<item>@string/menuitem_worldclock</item>
|
||||
<!-- dummy item -->
|
||||
<item>@string/menuitem_more</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_zepp_os_apps_values">
|
||||
<item>activity</item>
|
||||
<item>alarm</item>
|
||||
<item>alexa</item>
|
||||
<item>barometer</item>
|
||||
<item>breathing</item>
|
||||
<item>calendar</item>
|
||||
<item>compass</item>
|
||||
<item>countdown</item>
|
||||
<item>eventreminder</item>
|
||||
<item>events</item>
|
||||
<item>female_health</item>
|
||||
<item>findphone</item>
|
||||
<item>flashlight</item>
|
||||
<item>hr</item>
|
||||
<item>membership_cards</item>
|
||||
<item>music</item>
|
||||
<item>mutephone</item>
|
||||
<item>offline_voice</item>
|
||||
<item>one_tap_measuring</item>
|
||||
<item>pai</item>
|
||||
<item>personal_activity_intelligence</item>
|
||||
<item>phone</item>
|
||||
<item>pomodoro</item>
|
||||
<item>settings</item>
|
||||
<item>sleep</item>
|
||||
<item>spo2</item>
|
||||
<item>stopwatch</item>
|
||||
<item>stress</item>
|
||||
<item>sun_moon</item>
|
||||
<item>takephoto</item>
|
||||
<item>todo</item>
|
||||
<item>voice_memos</item>
|
||||
<item>weather</item>
|
||||
<item>workout_history</item>
|
||||
<item>workout</item>
|
||||
<item>workout_status</item>
|
||||
<item>worldclock</item>
|
||||
<!-- dummy item -->
|
||||
<item>more</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_huami2021_control_center">
|
||||
<item>@string/battery</item>
|
||||
<item>@string/menuitem_dnd</item>
|
||||
<item>@string/menuitem_sleep</item>
|
||||
<item>@string/menuitem_theater_mode</item>
|
||||
<item>@string/menuitem_calendar</item>
|
||||
<item>@string/menuitem_volume</item>
|
||||
<item>@string/menuitem_screen_always_lit</item>
|
||||
<item>@string/menuitem_brightness</item>
|
||||
<item>@string/menuitem_settings</item>
|
||||
<item>@string/menuitem_flashlight</item>
|
||||
<item>@string/menuitem_bluetooth</item>
|
||||
<item>@string/menuitem_wifi</item>
|
||||
<item>@string/menuitem_lockscreen</item>
|
||||
<item>@string/menuitem_findphone</item>
|
||||
<item>@string/menuitem_eject_water</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_huami2021_control_center_values">
|
||||
<item>battery</item>
|
||||
<item>dnd</item>
|
||||
<item>sleep</item>
|
||||
<item>theater_mode</item>
|
||||
<item>calendar</item>
|
||||
<item>volume</item>
|
||||
<item>screen_always_lit</item>
|
||||
<item>brightness</item>
|
||||
<item>settings</item>
|
||||
<item>flashlight</item>
|
||||
<item>bluetooth</item>
|
||||
<item>wifi</item>
|
||||
<item>lockscreen</item>
|
||||
<item>findphone</item>
|
||||
<item>eject_water</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_miband5_workout_activity_types">
|
||||
@ -1852,7 +2060,7 @@
|
||||
<item>1800</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="screen_timeout_5_to_15">
|
||||
<string-array name="screen_timeout">
|
||||
<item>@string/seconds_5</item>
|
||||
<item>@string/seconds_6</item>
|
||||
<item>@string/seconds_7</item>
|
||||
@ -1864,8 +2072,11 @@
|
||||
<item>@string/seconds_13</item>
|
||||
<item>@string/seconds_14</item>
|
||||
<item>@string/seconds_15</item>
|
||||
<item>@string/seconds_20</item>
|
||||
<item>@string/seconds_25</item>
|
||||
<item>@string/seconds_30</item>
|
||||
</string-array>
|
||||
<string-array name="screen_timeout_5_to_15_values">
|
||||
<string-array name="screen_timeout_values">
|
||||
<item>5</item>
|
||||
<item>6</item>
|
||||
<item>7</item>
|
||||
@ -1877,6 +2088,9 @@
|
||||
<item>13</item>
|
||||
<item>14</item>
|
||||
<item>15</item>
|
||||
<item>20</item>
|
||||
<item>25</item>
|
||||
<item>30</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="reminder_repeat">
|
||||
|
@ -58,6 +58,21 @@
|
||||
<string name="controlcenter_calibrate_device">Calibrate Device</string>
|
||||
<string name="controlcenter_get_heartrate_measurement">Get heart rate measurement</string>
|
||||
|
||||
<string name="accuracy">Accuracy</string>
|
||||
<string name="balanced">Balanced</string>
|
||||
<string name="power_saving">Power Saving</string>
|
||||
<string name="custom">Custom</string>
|
||||
<string name="single_band">Single Band</string>
|
||||
<string name="dual_band">Dual Band</string>
|
||||
<string name="low_power_gps">Low Power GPS</string>
|
||||
<string name="gps">GPS</string>
|
||||
<string name="gps_bds">GPS + BDS</string>
|
||||
<string name="gps_gnolass">GPS + GNOLASS</string>
|
||||
<string name="gps_galileo">GPS + GALILEO</string>
|
||||
<string name="all_satellites">All Satellites</string>
|
||||
<string name="speed_first">Speed first</string>
|
||||
<string name="accuracy_first">Accuracy First</string>
|
||||
|
||||
<string name="device_card_activity_card_title">Activity info on device card</string>
|
||||
<string name="device_card_activity_card_title_summary">Choose what activity details are displayed on device card</string>
|
||||
<string name="prefs_activity_in_device_card_title">Show Activity info on device card</string>
|
||||
@ -134,6 +149,7 @@
|
||||
<string name="fw_upgrade_notice_miband7">You are about to install the %s firmware on your Xiaomi Smart Band 7.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK!</string>
|
||||
<string name="fw_upgrade_notice_amazfit_gts3">You are about to install the %s firmware on your Amazfit GTS 3.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK!</string>
|
||||
<string name="fw_upgrade_notice_amazfit_gtr3">You are about to install the %s firmware on your Amazfit GTR 3.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK!</string>
|
||||
<string name="fw_upgrade_notice_amazfit_gtr4">You are about to install the %s firmware on your Amazfit GTR 4.\n\nYour band will reboot after installing the .zip file.\n\nPROCEED AT YOUR OWN RISK!</string>
|
||||
<string name="fw_upgrade_notice_amazfitx">You are about to install the %s firmware on your Amazfit X.\n\nPlease make sure to install the .fw file, and after that the .res file. Your band will reboot after installing the .fw file.\n\nNote: You do not have to install .res if it is exactly the same as the one previously installed.\n\nPROCEED AT YOUR OWN RISK!</string>
|
||||
<string name="fw_upgrade_notice_amazfitneo">You are about to install the %s firmware on your Amazfit Neo.
|
||||
\n
|
||||
@ -165,6 +181,8 @@
|
||||
<string name="pref_header_connection">Connection</string>
|
||||
<string name="pref_header_display">Display</string>
|
||||
<string name="pref_header_health">Health</string>
|
||||
<string name="pref_header_sound_vibration">Sound & Vibration</string>
|
||||
<string name="pref_header_offline_voice">Offline Voice</string>
|
||||
<string name="pref_header_time">Time</string>
|
||||
<string name="pref_header_workout">Workout</string>
|
||||
<string name="pref_header_equalizer">Equalizer</string>
|
||||
@ -414,10 +432,38 @@
|
||||
<string name="prefs_hr_alarm_activity">Heart rate alarm during sports activity</string>
|
||||
<string name="prefs_hr_alarm_low">Low limit</string>
|
||||
<string name="prefs_hr_alarm_high">High limit</string>
|
||||
<string name="pref_gps_header">GPS</string>
|
||||
<string name="pref_gps_mode_preset">GPS Mode</string>
|
||||
<string name="pref_gps_band">GPS Band</string>
|
||||
<string name="pref_gps_combination">GPS Combination</string>
|
||||
<string name="pref_gps_satellite_search">Satellite Search</string>
|
||||
<string name="pref_crown_vibration">Crown Vibration</string>
|
||||
<string name="pref_alert_tone">Alert Tone</string>
|
||||
<string name="pref_cover_to_mute">Cover to Mute</string>
|
||||
<string name="pref_vibrate_for_alert">Vibrate for Alert</string>
|
||||
<string name="pref_text_to_speech">Text to Speech</string>
|
||||
<string name="offline_voice_respond_turn_wrist">Respond when turning the wrist</string>
|
||||
<string name="offline_voice_respond_screen_on">Respond when screen on</string>
|
||||
<string name="offline_voice_response_during_screen_lighting">Respond during screen lighting</string>
|
||||
<string name="pref_agps_header">AGPS</string>
|
||||
<string name="pref_agps_expiry_reminder_enabled">AGPS Expiry Reminder</string>
|
||||
<string name="pref_agps_expiry_reminder_time">AGPS Expiry Reminder Time</string>
|
||||
<string name="pref_workout_start_on_phone_title">Fitness app tracking</string>
|
||||
<string name="pref_workout_start_on_phone_summary">Start/stop fitness app tracking on phone when a GPS workout is started on the band</string>
|
||||
<string name="pref_workout_send_gps_title">Send GPS during workout</string>
|
||||
<string name="pref_workout_send_gps_summary">Send the current GPS location to the band during a workout</string>
|
||||
<string name="pref_workout_detection_title">Workout Detection</string>
|
||||
<string name="pref_workout_detection_summary">Detect workout automatically</string>
|
||||
<string name="pref_workout_detection_categories_title">Workout Categories</string>
|
||||
<string name="pref_workout_detection_categories_summary">Workouts categories to detect automatically</string>
|
||||
<string name="pref_workout_detection_alert_title">Alert</string>
|
||||
<string name="pref_workout_detection_alert_summary">Notify when a workout is detected</string>
|
||||
<string name="pref_workout_detection_sensitivity">Sensitivity</string>
|
||||
<string name="pref_sleep_mode_title">Sleep Mode</string>
|
||||
<string name="pref_sleep_mode_sleep_screen_title">Sleep Screen</string>
|
||||
<string name="pref_sleep_mode_sleep_screen_summary">Show the Sleep Screen when waking the screen during sleep mode, to reduce distractions</string>
|
||||
<string name="pref_sleep_mode_smart_enable_title">Smart Enable</string>
|
||||
<string name="pref_sleep_mode_smart_enable_summary">Enable the sleep mode automatically when wearing the band during sleep</string>
|
||||
<!-- Auto export preferences -->
|
||||
<string name="pref_header_auto_export">Auto export</string>
|
||||
<string name="pref_title_auto_export_enabled">Auto export enabled</string>
|
||||
@ -486,6 +532,8 @@
|
||||
<string name="right">Right</string>
|
||||
<string name="horizontal">Horizontal</string>
|
||||
<string name="vertical">Vertical</string>
|
||||
<string name="buttons_on_left">Buttons on left</string>
|
||||
<string name="buttons_on_right">Buttons on right</string>
|
||||
<string name="miband_pairing_using_dummy_userdata">No valid user data given, using dummy user data for now.</string>
|
||||
<string name="miband_pairing_tap_hint">When your Mi Band vibrates and blinks, tap it a few times in a row.</string>
|
||||
<string name="appinstaller_install">Install</string>
|
||||
@ -506,7 +554,9 @@
|
||||
<string name="busy_task_fetch_activity_data">Fetching activity data</string>
|
||||
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
|
||||
<string name="prefs_wearside">Wearing left or right?</string>
|
||||
<string name="prefs_weardirection">Wearing direction</string>
|
||||
<string name="pref_screen_vibration_profile">Vibration profile</string>
|
||||
<string name="vibration_profile_default">Default</string>
|
||||
<string name="vibration_profile_staccato">Staccato</string>
|
||||
<string name="vibration_profile_short">Short</string>
|
||||
<string name="vibration_profile_medium">Medium</string>
|
||||
@ -529,6 +579,8 @@
|
||||
<string name="pref_screen_notification_profile_inactivity">Inactivity notification</string>
|
||||
<string name="pref_screen_notification_profile_low_power">Low power warning</string>
|
||||
<string name="pref_screen_notification_profile_anti_loss">Anti-loss warning</string>
|
||||
<string name="pref_screen_notification_profile_schedule">Schedule</string>
|
||||
<string name="pref_screen_notification_profile_todo_list">To-Do List</string>
|
||||
<string name="prefs_title_heartrate_measurement_interval">Whole day HR measurement</string>
|
||||
<string name="pref_screen_notification_profile_event_reminder">Event reminder</string>
|
||||
<string name="pref_screen_notification_profile_find_device">Find device</string>
|
||||
@ -712,6 +764,7 @@
|
||||
<string name="seconds_14">14 seconds</string>
|
||||
<string name="seconds_15">15 seconds</string>
|
||||
<string name="seconds_20">20 seconds</string>
|
||||
<string name="seconds_25">25 seconds</string>
|
||||
<string name="seconds_30">30 seconds</string>
|
||||
<string name="minutes_1">1 minute</string>
|
||||
<string name="minutes_5">5 minutes</string>
|
||||
@ -725,6 +778,8 @@
|
||||
<string name="pref_title_dont_ack_transfer">Do not ACK activity data transfer</string>
|
||||
<string name="pref_summary_dont_ack_transfers">If not ACKed to the band, activity data is not cleared. Useful if GB is used together with other apps.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Will keep activity data on the device even after synchronization. Useful if GB is used together with other apps.</string>
|
||||
<string name="pref_enable_unsupported_settings_title">Enable unsupported settings</string>
|
||||
<string name="pref_enable_unsupported_settings_summary">This will enable access to all available settings, even if unsupported by the device. This can cause instability and crashes on the device.</string>
|
||||
<string name="pref_title_low_latency_fw_update">Use low-latency mode for firmware flashing</string>
|
||||
<string name="pref_summary_low_latency_fw_update">This might help on devices where firmware flashing fails.</string>
|
||||
<string name="pref_title_third_party_app_device_settings">Allow 3rd party apps to change settings</string>
|
||||
@ -790,6 +845,8 @@
|
||||
<string name="mi2_prefs_heart_rate_monitoring">Heart Rate Monitoring</string>
|
||||
<string name="mi2_prefs_heart_rate_monitoring_summary">Configure heart rate monitoring</string>
|
||||
<string name="prefs_always_on_display">Always On Display</string>
|
||||
<string name="prefs_always_on_display_follow_watchface">Style follows Watchface</string>
|
||||
<string name="prefs_always_on_display_style">Style</string>
|
||||
<string name="prefs_always_on_display_summary">Keep the band\'s display always on</string>
|
||||
<string name="prefs_password">Password</string>
|
||||
<string name="prefs_password_summary">Lock the band with a password when removed from the wrist</string>
|
||||
@ -806,6 +863,8 @@
|
||||
<string name="mi3_prefs_night_mode_summary">Lower band screen brightness automatically at night</string>
|
||||
<string name="bip_prefs_shortcuts">Shortcuts</string>
|
||||
<string name="bip_prefs_shotcuts_summary">Choose the shortcuts on the band screen</string>
|
||||
<string name="prefs_control_center">Control Center</string>
|
||||
<string name="prefs_control_center_summary">Choose the items on the control center dropdown</string>
|
||||
<string name="prefs_activate_display_on_lift_sensitivity">Sensitivity</string>
|
||||
<string name="prefs_screen_timeout">Screen Timeout</string>
|
||||
<string name="mi5_prefs_workout_activity_types">Workout Activity Types</string>
|
||||
@ -863,6 +922,7 @@
|
||||
<string name="activity_prefs_gender">Gender</string>
|
||||
<string name="activity_prefs_height_cm">Height in cm</string>
|
||||
<string name="activity_prefs_weight_kg">Weight in kg</string>
|
||||
<string name="activity_prefs_target_weight_kg">Target weight in kg</string>
|
||||
<string name="activity_prefs_step_length_cm">Step length in cm</string>
|
||||
<!-- Settings - Charts Preferences -->
|
||||
<string name="pref_header_charts">Charts Settings</string>
|
||||
@ -903,6 +963,8 @@
|
||||
<string name="activity_prefs_calories_burnt">Daily target: calories burnt</string>
|
||||
<string name="activity_prefs_distance_meters">Daily target: distance in meters</string>
|
||||
<string name="activity_prefs_activetime_minutes">Daily target: active time in minutes</string>
|
||||
<string name="activity_prefs_goal_standing_time_minutes">Daily target: standing time in minutes</string>
|
||||
<string name="activity_prefs_goal_fat_burn_time_minutes">Daily target: fat burn time in minutes</string>
|
||||
<string name="pref_title_pebble_health_store_raw">Store raw record in the database</string>
|
||||
<string name="pref_summary_pebble_health_store_raw">Stores the data \"as is\", increasing the database usage to allow for later interpretation.</string>
|
||||
<string name="action_db_management">Data management</string>
|
||||
@ -1014,10 +1076,12 @@
|
||||
<string name="activity_type_running">Running</string>
|
||||
<string name="activity_type_outdoor_running">Outdoor Running</string>
|
||||
<string name="activity_type_walking">Walking</string>
|
||||
<string name="activity_type_indoor_walking">Indoor Walking</string>
|
||||
<string name="activity_type_freestyle">Freestyle</string>
|
||||
<string name="activity_type_hiking">Hiking</string>
|
||||
<string name="activity_type_climbing">Climbing</string>
|
||||
<string name="activity_type_swimming">Swimming</string>
|
||||
<string name="activity_type_pool_swimming">Pool Swimming</string>
|
||||
<string name="activity_type_swimming_openwater">Swimming (Open water)</string>
|
||||
<string name="activity_type_indoor_cycling">Indoor Cycling</string>
|
||||
<string name="activity_type_outdoor_cycling">Outdoor Cycling</string>
|
||||
@ -1088,6 +1152,7 @@
|
||||
<string name="devicetype_miband7">Xiaomi Smart Band 7</string>
|
||||
<string name="devicetype_amazfit_gts3">Amazfit GTS 3</string>
|
||||
<string name="devicetype_amazfit_gtr3">Amazfit GTR 3</string>
|
||||
<string name="devicetype_amazfit_gtr4">Amazfit GTR 4</string>
|
||||
<string name="devicetype_amazfit_band5">Amazfit Band 5</string>
|
||||
<string name="devicetype_amazfit_neo">Amazfit Neo</string>
|
||||
<string name="devicetype_amazfit_bip">Amazfit Bip</string>
|
||||
@ -1208,7 +1273,24 @@
|
||||
<string name='menuitem_workout_history'>Workout History</string>
|
||||
<string name='menuitem_female_health'>Female Health</string>
|
||||
<string name='menuitem_workout_status'>Workout Status</string>
|
||||
<string name='menuitem_calendar'>Calendar</string>
|
||||
<string name='menuitem_todo'>To-Do</string>
|
||||
<string name='menuitem_voice_memos'>Voice Memos</string>
|
||||
<string name='menuitem_sun_moon'>Sun & Moon</string>
|
||||
<string name='menuitem_one_tap_measuring'>One-tap Measuring</string>
|
||||
<string name='menuitem_offline_voice'>Offline Voice</string>
|
||||
<string name='menuitem_membership_cards'>Membership Cards</string>
|
||||
<string name='menuitem_phone'>Phone</string>
|
||||
<string name='menuitem_theater_mode'>Theater Mode</string>
|
||||
<string name='menuitem_volume'>Volume</string>
|
||||
<string name='menuitem_screen_always_lit'>Screen Always Lit</string>
|
||||
<string name='menuitem_brightness'>Brightness</string>
|
||||
<string name='menuitem_bluetooth'>Bluetooth</string>
|
||||
<string name='menuitem_wifi'>Wi-Fi</string>
|
||||
<string name='menuitem_lockscreen'>Lockscreen</string>
|
||||
<string name='menuitem_eject_water'>Eject Water</string>
|
||||
<string name="menuitem_unknown_app">Unknown (%s)</string>
|
||||
<string name="menuitem_unsupported">[UNSUPPORTED] %s</string>
|
||||
<string name="watch9_time_minutes">Minutes:</string>
|
||||
<string name="watch9_time_hours">Hours:</string>
|
||||
<string name="watch9_time_seconds">Seconds:</string>
|
||||
@ -1290,6 +1372,8 @@
|
||||
<string name="hr_appname_workout">Workout</string>
|
||||
<string name="hr_appname_stopwatch">Stopwatch</string>
|
||||
<string name="hr_appname_commute">Commute</string>
|
||||
<string name="pref_title_upper_button_long_press_action">Upper Button long press action</string>
|
||||
<string name="pref_title_lower_button_short_press_action">Lower Button short press action</string>
|
||||
<string name="pref_title_upper_button_function_short">Upper Button short</string>
|
||||
<string name="pref_title_middle_button_function_short">Middle Button short</string>
|
||||
<string name="pref_title_lower_button_function_short">Lower Button short</string>
|
||||
@ -1753,6 +1837,7 @@
|
||||
<string name="sony_speak_to_chat_sensitivity_auto">Automatic</string>
|
||||
<string name="sony_speak_to_chat_sensitivity_high">High</string>
|
||||
<string name="sony_speak_to_chat_sensitivity_low">Low</string>
|
||||
<string name="sony_speak_to_chat_sensitivity_standard">Standard</string>
|
||||
<string name="sony_speak_to_chat_focus_on_voice">Focus on Voice</string>
|
||||
<string name="sony_speak_to_chat_timeout">Timeout</string>
|
||||
<string name="sony_speak_to_chat_timeout_off">Off</string>
|
||||
@ -1775,6 +1860,8 @@
|
||||
<string name="sony_button_mode_ambient_sound_control">Ambient Sound Control</string>
|
||||
<string name="sony_button_mode_playback_control">Playback Control</string>
|
||||
<string name="sony_button_mode_volume_control">Volume Control</string>
|
||||
<string name="pref_screen_auto_brightness_title">Auto Brightness</string>
|
||||
<string name="pref_screen_auto_brightness_summary">Adjust screen brightness according to ambient light</string>
|
||||
<string name="pref_screen_brightness">Screen Brightness</string>
|
||||
<string name="watchface_widget_type_custom">Custom widget</string>
|
||||
<string name="watchface_dialog_widget_timezone">Time zone</string>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Note: these are not translated! They are used as preference keys -->
|
||||
<item name="p_default" type="string">default</item>
|
||||
<item name="p_staccato" type="string">staccato</item>
|
||||
<item name="p_short" type="string">short</item>
|
||||
<item name="p_medium" type="string">medium</item>
|
||||
|
@ -31,6 +31,12 @@
|
||||
android:maxLength="3"
|
||||
android:title="@string/activity_prefs_weight_kg" />
|
||||
|
||||
<EditTextPreference
|
||||
android:inputType="number"
|
||||
android:key="activity_user_goal_weight_kg"
|
||||
android:maxLength="3"
|
||||
android:title="@string/activity_prefs_target_weight_kg" />
|
||||
|
||||
<EditTextPreference
|
||||
android:inputType="number"
|
||||
android:key="activity_user_step_length_cm"
|
||||
@ -70,5 +76,19 @@
|
||||
android:key="activity_user_activetime_minutes"
|
||||
android:maxLength="3"
|
||||
android:title="@string/activity_prefs_activetime_minutes" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="12"
|
||||
android:inputType="number"
|
||||
android:key="activity_user_goal_standing_time_minutes"
|
||||
android:maxLength="2"
|
||||
android:title="@string/activity_prefs_goal_standing_time_minutes" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="30"
|
||||
android:inputType="number"
|
||||
android:key="activity_user_goal_fat_burn_time_minutes"
|
||||
android:maxLength="3"
|
||||
android:title="@string/activity_prefs_goal_fat_burn_time_minutes" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
@ -27,5 +27,18 @@
|
||||
android:defaultValue="00:00"
|
||||
android:key="always_on_display_end"
|
||||
android:title="@string/mi2_prefs_do_not_disturb_end" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="always_on_display_follow_watchface"
|
||||
android:title="@string/prefs_always_on_display_follow_watchface" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_huami2021_empty_array"
|
||||
android:entryValues="@array/pref_huami2021_empty_array"
|
||||
android:key="always_on_display_style"
|
||||
android:summary="%s"
|
||||
android:title="@string/prefs_always_on_display_style" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_zepp_os_apps"
|
||||
android:entryValues="@array/pref_zepp_os_apps_values"
|
||||
android:icon="@drawable/ic_smart_button"
|
||||
android:key="pref_button_action_lower_short"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_title_lower_button_short_press_action" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_zepp_os_apps"
|
||||
android:entryValues="@array/pref_zepp_os_apps_values"
|
||||
android:icon="@drawable/ic_smart_button"
|
||||
android:key="pref_button_action_upper_long"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_title_upper_button_long_press_action" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_block"
|
||||
android:key="screen_do_not_disturb"
|
||||
android:key="pref_screen_do_not_disturb"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_do_not_disturb_summary"
|
||||
android:title="@string/mi2_prefs_do_not_disturb">
|
||||
|
62
app/src/main/res/xml/devicesettings_gps_agps.xml
Normal file
62
app/src/main/res/xml/devicesettings_gps_agps.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_gps_location"
|
||||
android:key="pref_header_gps"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_gps_header">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_gps_header_category"
|
||||
android:title="@string/pref_gps_header">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_gps_mode_preset"
|
||||
android:entryValues="@array/pref_gps_mode_preset_values"
|
||||
android:key="pref_gps_mode_preset"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_gps_mode_preset" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_gps_band"
|
||||
android:entryValues="@array/pref_gps_band_values"
|
||||
android:key="pref_gps_band"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_gps_band" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_gps_combination"
|
||||
android:entryValues="@array/pref_gps_combination_values"
|
||||
android:key="pref_gps_combination"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_gps_combination" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/pref_gps_satellite_search"
|
||||
android:entryValues="@array/pref_gps_satellite_search_values"
|
||||
android:key="pref_gps_satellite_search"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_gps_satellite_search" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_header_agps"
|
||||
android:title="@string/pref_agps_header">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_agps_expiry_reminder_enabled"
|
||||
android:title="@string/pref_agps_expiry_reminder_enabled" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="20:00"
|
||||
android:dependency="pref_agps_expiry_reminder_enabled"
|
||||
android:key="pref_agps_expiry_reminder_time"
|
||||
android:title="@string/pref_agps_expiry_reminder_time" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory
|
||||
android:key="pref_header_sound_vibration"
|
||||
android:title="@string/pref_header_sound_vibration" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_heartrate"
|
||||
android:key="heartrate_monitoring_key"
|
||||
android:key="pref_screen_heartrate_monitoring"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_heart_rate_monitoring_alerts_summary"
|
||||
android:title="@string/mi2_prefs_heart_rate_monitoring">
|
||||
@ -38,6 +38,15 @@
|
||||
android:title="@string/prefs_title_heartrate_measurement_interval" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Activity Monitoring -->
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_activity_unknown_small"
|
||||
android:key="heartrate_activity_monitoring"
|
||||
android:summary="@string/prefs_activity_monitoring_description"
|
||||
android:title="@string/prefs_activity_monitoring_title" />
|
||||
|
||||
<!-- Heart Rate Alerts -->
|
||||
|
||||
<PreferenceCategory
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<com.mobeta.android.dslv.DragSortListPreference
|
||||
android:defaultValue="@array/pref_huami2021_empty_array"
|
||||
android:dialogTitle="@string/bip_prefs_shortcuts"
|
||||
android:entries="@array/pref_huami2021_control_center"
|
||||
android:entryValues="@array/pref_huami2021_control_center_values"
|
||||
android:icon="@drawable/ic_menu"
|
||||
android:key="control_center_sortable"
|
||||
android:persistent="true"
|
||||
android:summary="@string/prefs_control_center_summary"
|
||||
android:title="@string/prefs_control_center" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<com.mobeta.android.dslv.DragSortListPreference
|
||||
android:defaultValue="@array/pref_huami2021_display_items"
|
||||
android:defaultValue="@array/pref_huami2021_empty_array"
|
||||
android:dialogTitle="@string/mi2_prefs_display_items"
|
||||
android:entries="@array/pref_huami2021_display_items"
|
||||
android:entryValues="@array/pref_huami2021_display_items"
|
||||
android:entries="@array/pref_zepp_os_apps"
|
||||
android:entryValues="@array/pref_zepp_os_apps_values"
|
||||
android:icon="@drawable/ic_widgets"
|
||||
android:key="display_items_sortable"
|
||||
android:persistent="true"
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<com.mobeta.android.dslv.DragSortListPreference
|
||||
android:icon="@drawable/ic_shortcut"
|
||||
android:defaultValue="@array/pref_huami2021_shortcuts"
|
||||
android:defaultValue="@array/pref_huami2021_empty_array"
|
||||
android:dialogTitle="@string/bip_prefs_shortcuts"
|
||||
android:entries="@array/pref_huami2021_shortcuts"
|
||||
android:entryValues="@array/pref_huami2021_shortcuts"
|
||||
android:entries="@array/pref_zepp_os_apps"
|
||||
android:entryValues="@array/pref_zepp_os_apps_values"
|
||||
android:icon="@drawable/ic_shortcut"
|
||||
android:key="shortcuts_sortable"
|
||||
android:persistent="true"
|
||||
android:summary="@string/bip_prefs_shotcuts_summary"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_chair"
|
||||
android:key="screen_inactivity"
|
||||
android:key="pref_screen_inactivity_extended"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings">
|
||||
@ -10,8 +10,8 @@
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="inactivity_warnings_enable"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary" />
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings" />
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
|
||||
android:defaultValue="06:00"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_chair"
|
||||
android:key="screen_inactivity_extended"
|
||||
android:key="pref_screen_inactivity_extended"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings">
|
||||
@ -13,8 +13,8 @@
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="inactivity_warnings_enable"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings"
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary" />
|
||||
android:summary="@string/mi2_prefs_inactivity_warnings_summary"
|
||||
android:title="@string/mi2_prefs_inactivity_warnings" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="4"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_arrow_upward"
|
||||
android:key="screen_liftwrist_display"
|
||||
android:key="pref_screen_lift_wrist"
|
||||
android:persistent="false"
|
||||
android:title="@string/mi2_prefs_activate_display_on_lift">
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_brightness_2"
|
||||
android:key="screen_night_mode"
|
||||
android:key="pref_screen_night_mode"
|
||||
android:persistent="false"
|
||||
android:summary="@string/mi3_prefs_night_mode_summary"
|
||||
android:title="@string/mi3_prefs_night_mode">
|
||||
|
36
app/src/main/res/xml/devicesettings_offline_voice.xml
Normal file
36
app/src/main/res/xml/devicesettings_offline_voice.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_voice"
|
||||
android:key="pref_screen_offline_voice"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_header_offline_voice">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="en_US"
|
||||
android:entries="@array/pref_language_all"
|
||||
android:entryValues="@array/pref_language_all_values"
|
||||
android:icon="@drawable/ic_language"
|
||||
android:key="offline_voice_language"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_title_language" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_rotate_left"
|
||||
android:key="offline_voice_respond_turn_wrist"
|
||||
android:title="@string/offline_voice_respond_turn_wrist" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_always_on_display"
|
||||
android:key="offline_voice_respond_screen_on"
|
||||
android:title="@string/offline_voice_respond_screen_on" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_always_on_display"
|
||||
android:key="offline_voice_response_during_screen_lighting"
|
||||
android:title="@string/offline_voice_response_during_screen_lighting" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -2,7 +2,7 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_password"
|
||||
android:key="password_monitoring_key"
|
||||
android:key="pref_screen_password"
|
||||
android:persistent="false"
|
||||
android:summary="@string/prefs_password_summary"
|
||||
android:title="@string/prefs_password">
|
||||
@ -19,6 +19,6 @@
|
||||
android:icon="@drawable/ic_password"
|
||||
android:inputType="numberPassword"
|
||||
android:key="pref_password"
|
||||
android:title="@string/prefs_password"/>
|
||||
android:title="@string/prefs_password" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_wb_sunny"
|
||||
android:key="pref_screen_auto_brightness"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_screen_brightness">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_wb_sunny"
|
||||
android:key="screen_auto_brightness"
|
||||
android:summary="@string/pref_screen_auto_brightness_summary"
|
||||
android:title="@string/pref_screen_auto_brightness_title" />
|
||||
|
||||
<SeekBarPreference
|
||||
android:defaultValue="50"
|
||||
android:icon="@drawable/ic_wb_sunny"
|
||||
android:key="screen_brightness"
|
||||
android:max="100"
|
||||
android:title="@string/pref_screen_brightness" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -2,8 +2,8 @@
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ListPreference
|
||||
android:defaultValue="5"
|
||||
android:entries="@array/screen_timeout_5_to_15"
|
||||
android:entryValues="@array/screen_timeout_5_to_15_values"
|
||||
android:entries="@array/screen_timeout"
|
||||
android:entryValues="@array/screen_timeout_values"
|
||||
android:key="screen_timeout"
|
||||
android:icon="@drawable/ic_hourglass_empty"
|
||||
android:summary="%s"
|
23
app/src/main/res/xml/devicesettings_sleep_mode.xml
Normal file
23
app/src/main/res/xml/devicesettings_sleep_mode.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_activity_sleep"
|
||||
android:key="pref_screen_sleep_mode"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_sleep_mode_title">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_activity_sleep"
|
||||
android:key="pref_sleep_mode_sleep_screen"
|
||||
android:summary="@string/pref_sleep_mode_sleep_screen_summary"
|
||||
android:title="@string/pref_sleep_mode_sleep_screen_title" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_auto_awesome"
|
||||
android:key="pref_sleep_mode_smart_enable"
|
||||
android:summary="@string/pref_sleep_mode_smart_enable_summary"
|
||||
android:title="@string/pref_sleep_mode_smart_enable_title" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
46
app/src/main/res/xml/devicesettings_sound_and_vibration.xml
Normal file
46
app/src/main/res/xml/devicesettings_sound_and_vibration.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_volume_up"
|
||||
android:key="pref_screen_sound_and_vibration"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_header_sound_vibration">
|
||||
|
||||
<SeekBarPreference
|
||||
android:defaultValue="50"
|
||||
android:icon="@drawable/ic_volume_up"
|
||||
android:key="volume"
|
||||
android:max="100"
|
||||
android:title="@string/menuitem_volume" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_rotate_left"
|
||||
android:key="crown_vibration"
|
||||
android:title="@string/pref_crown_vibration" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_warning_gray"
|
||||
android:key="alert_tone"
|
||||
android:title="@string/pref_alert_tone" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_volume_off"
|
||||
android:key="cover_to_mute"
|
||||
android:title="@string/pref_cover_to_mute" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_vibration"
|
||||
android:key="vibrate_for_alert"
|
||||
android:title="@string/pref_vibrate_for_alert" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_voice"
|
||||
android:key="text_to_speech"
|
||||
android:title="@string/pref_text_to_speech" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -19,7 +19,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_generic" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_short"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_app_alerts"
|
||||
@ -49,7 +49,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_incoming_call" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_ring"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_incoming_call"
|
||||
@ -79,7 +79,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_sms" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_staccato"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_incoming_sms"
|
||||
@ -109,7 +109,7 @@
|
||||
<PreferenceCategory android:title="@string/mi2_prefs_goal_notification" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_long"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_goal_notification"
|
||||
@ -139,7 +139,7 @@
|
||||
<PreferenceCategory android:title="@string/vibration_profile_alarm_clock" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_long"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_alarm"
|
||||
@ -169,7 +169,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_idle_alerts" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_medium"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_idle_alerts"
|
||||
@ -199,7 +199,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_event_reminder" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_long"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_event_reminder"
|
||||
@ -229,7 +229,7 @@
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_find_device" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_long"
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_find_band"
|
||||
@ -249,5 +249,64 @@
|
||||
android:title="@string/vibration_try"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="vibration_profile_key_todo_list"
|
||||
android:icon="@drawable/ic_checklist"
|
||||
android:title="@string/pref_screen_notification_profile_todo_list"
|
||||
android:persistent="false">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_todo_list" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_todo_list"
|
||||
android:title="@string/miband_prefs_vibration"
|
||||
android:summary="%s" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="2"
|
||||
android:inputType="number"
|
||||
android:key="huami_vibration_count_todo_list"
|
||||
android:maxLength="1"
|
||||
android:title="@string/pref_title_notifications_repetitions" />
|
||||
|
||||
<Preference
|
||||
android:persistent="false"
|
||||
android:key="huami_vibration_try_todo_list"
|
||||
android:title="@string/vibration_try"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="vibration_profile_key_schedule"
|
||||
android:icon="@drawable/ic_calendar_to"
|
||||
android:title="@string/pref_screen_notification_profile_schedule"
|
||||
android:persistent="false">
|
||||
|
||||
<!-- workaround for missing toolbar -->
|
||||
<PreferenceCategory android:title="@string/pref_screen_notification_profile_schedule" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/p_default"
|
||||
android:entries="@array/vibration_profile"
|
||||
android:entryValues="@array/vibration_profile_values"
|
||||
android:key="huami_vibration_profile_schedule"
|
||||
android:title="@string/miband_prefs_vibration"
|
||||
android:summary="%s" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="2"
|
||||
android:inputType="number"
|
||||
android:key="huami_vibration_count_schedule"
|
||||
android:maxLength="1"
|
||||
android:title="@string/pref_title_notifications_repetitions" />
|
||||
|
||||
<Preference
|
||||
android:persistent="false"
|
||||
android:key="huami_vibration_try_schedule"
|
||||
android:title="@string/vibration_try"/>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
11
app/src/main/res/xml/devicesettings_weardirection.xml
Normal file
11
app/src/main/res/xml/devicesettings_weardirection.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ListPreference
|
||||
android:defaultValue="buttons_on_right"
|
||||
android:entries="@array/weardirection"
|
||||
android:entryValues="@array/weardirection_values"
|
||||
android:icon="@drawable/ic_switch_left"
|
||||
android:key="weardirection"
|
||||
android:summary="%s"
|
||||
android:title="@string/prefs_weardirection" />
|
||||
</androidx.preference.PreferenceScreen>
|
35
app/src/main/res/xml/devicesettings_workout_detection.xml
Normal file
35
app/src/main/res/xml/devicesettings_workout_detection.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_activity_unknown_small"
|
||||
android:key="pref_header_workout_detection"
|
||||
android:persistent="false"
|
||||
android:summary="@string/pref_workout_detection_summary"
|
||||
android:title="@string/pref_workout_detection_title">
|
||||
|
||||
<MultiSelectListPreference
|
||||
android:defaultValue="@array/pref_huami2021_empty_array"
|
||||
android:dialogTitle="@string/pref_workout_detection_categories_title"
|
||||
android:entries="@array/pref_workout_detection_categories"
|
||||
android:entryValues="@array/pref_workout_detection_categories_values"
|
||||
android:icon="@drawable/ic_activity_unknown_small"
|
||||
android:key="workout_detection_categories"
|
||||
android:summary="@string/pref_workout_detection_categories_summary"
|
||||
android:title="@string/pref_workout_detection_categories_title" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_notifications"
|
||||
android:key="workout_detection_alert"
|
||||
android:summary="@string/pref_workout_detection_alert_summary"
|
||||
android:title="@string/pref_workout_detection_alert_title" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue=""
|
||||
android:entries="@array/workout_detection_sensitivity"
|
||||
android:entryValues="@array/workout_detection_sensitivity_values"
|
||||
android:key="workout_detection_sensitivity"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_workout_detection_sensitivity" />
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
@ -153,7 +153,7 @@ class TestDeviceSupport extends AbstractDeviceSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhoneFound() {
|
||||
public void onFindPhone(boolean start) {
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user