1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-07-21 22:31:16 +02:00
 Conflicts:
	GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
This commit is contained in:
mamutcho 2020-04-20 14:42:20 +03:00
commit 61da55e0de
89 changed files with 4992 additions and 547 deletions

View File

@ -1,4 +1,24 @@
### Changelog
#### Version 0.43.2
* Fossil Hybrid HR: Allow choosing and cropping image to be set as watch background
* Fossil Hybrid HR: Option to draw circles around widgets
* Fossil Hybrid HR: Experimenal firmware update support
* Fossil Hybrid HR: Fix vibration strength setting
* Huami: Do not display firmware information and whitelist information when flashing watchfaces
* Huami: Disable air quality indicator on Huami devices instead of showing 0
* Bangle.js: Change encoded char set to match Espruino's 8 bit fonts
* Steps/Sleep averages: Skip days with zero data
#### Version 0.43.1
* Initial support for Amazfit Bip S (incomplete, needs the official app once to obtain the pairing key)
* Amazift Bip Lite: Allow relaxing firmware checks to allow flashing of the regular Bip firmware (for the brave)
* Fossil Hybrid HR: Fix notification history on newer firmwares
* Fossil Hybrid HR: Add option to disable widget circle
* Bangle.js: Don't set time if the option is turned off in settings
* Bangle.js: DST and time zone fixes
* Add Arabic-style Eastern Arabic numerals to transliteration
#### Version 0.43.0
* Initial support for Fossil Hybrid HR (needs complicated key extraction, read wiki)
* Fossil: Allow switching off the Q Icon and use the default Gadgetbridge icon

View File

@ -43,7 +43,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(24, MAIN_PACKAGE + ".entities");
Schema schema = new Schema(25, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@ -74,6 +74,7 @@ public class GBDaoGenerator {
addWatchXPlusHealthActivitySample(schema, user, device);
addWatchXPlusHealthActivityKindOverlay(schema, user, device);
addHybridHRActivitySample(schema, user, device);
addCalendarSyncState(schema, device);
addAlarms(schema, user, device);
@ -344,6 +345,23 @@ public class GBDaoGenerator {
return activitySample;
}
private static Entity addHybridHRActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "HybridHRActivitySample");
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractHybridHRActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty("calories").notNull();
activitySample.addIntProperty("variability").notNull();
activitySample.addIntProperty("max_variability").notNull();
activitySample.addIntProperty("heartrate_quality").notNull();
activitySample.addBooleanProperty("active").notNull();
activitySample.addByteProperty("wear_type").notNull();
addHeartRateProperties(activitySample);
return activitySample;
}
private static Entity addWatchXPlusHealthActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "WatchXPlusActivitySample");
activitySample.implementsSerializable();

View File

@ -27,15 +27,17 @@ vendor's servers.
[List of changes](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/master/CHANGELOG.md)
## Supported Devices (Some of them WIP and some of them without maintainer)
## Supported Devices (WARNING: Some of them WIP and some of them without maintainer)
* Amazfit Bip [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip)
* Amazfit Bip Lite (NOT RECOMMENDED, NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-Lite)
* Amazfit Bip Lite (WARNING: NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Bip-Lite)
* Amazfit Bip S (WARNING: NEEDS MI FIT WITH ACCOUNT ONCE)
* Amazfit Cor [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor)
* Amazfit Cor 2 [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-Cor-2)
* Amazfit GTR (NOT RECOMMENDED, NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR)
* Amazfit GTS (NOT RECOMMENDED, NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS)
* Amazfit GTR (WARNING: NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTR)
* Amazfit GTS (WARNING: NEEDS MI FIT WITH ACCOUNT ONCE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Amazfit-GTS)
* BFH-16
* Casio GB-6900B
* Fossil Hybrid HR (WARNING: NEEDS FOSSIL APP WITH ACCOUNT ONCE AND COMPLICATED PROCEDURE) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Fossil-Hybrid-HR)
* Fossil Q Hybrid
* HPlus Devices (e.g. ZeBand) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/HPlus)
* iTag
@ -83,7 +85,7 @@ Please see [FEATURES.md](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/ma
* Jean-François Greffier (Mi Scale 2)
* Johannes Schmitt (BFH-16)
* Lukas Schwichtenberg (Makibes HR3)
* Daniel Dakhno (Fossil Q Hybrid)
* Daniel Dakhno (Fossil Q Hybrid, Fossil Hybrid HR)
* Gordon Williams (Bangle.js)
* Pavel Elagin (JYou Y5)
* Taavi Eomäe (iTag)

View File

@ -25,8 +25,8 @@ android {
targetSdkVersion 28
// Note: always bump BOTH versionCode and versionName!
versionName "0.43.0"
versionCode 169
versionName "0.43.2"
versionCode 171
vectorDrawables.useSupportLibrary = true
}
buildTypes {

View File

@ -517,6 +517,9 @@
<activity
android:name=".devices.qhybrid.HRConfigActivity"
android:exported="true" />
<activity
android:name=".devices.qhybrid.ImageEditActivity"
android:exported="true" />
</application>
</manifest>

View File

@ -59,6 +59,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
protected static final Logger LOG = LoggerFactory.getLogger(AbstractWeekChartFragment.class);
protected final int TOTAL_DAYS = getRangeDays();
protected int TOTAL_DAYS_FOR_AVERAGE = 0;
private Locale mLocale;
private int mTargetValue = 0;
@ -124,10 +125,17 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
ArrayList<String> labels = new ArrayList<String>();
long balance = 0;
long daily_balance=0;
TOTAL_DAYS_FOR_AVERAGE=0;
for (int counter = 0; counter < TOTAL_DAYS; counter++) {
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
daily_balance=calculateBalance(amounts);
if (daily_balance>0){
TOTAL_DAYS_FOR_AVERAGE++;
}
balance += calculateBalance(amounts);
balance += daily_balance;
entries.add(new BarEntry(counter, getTotalsForActivityAmounts(amounts)));
labels.add(getWeeksChartsLabel(day));
day.add(Calendar.DATE, 1);
@ -146,8 +154,8 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
barChart.getAxisLeft().addLimitLine(target);
float average = 0;
if (TOTAL_DAYS > 0) {
average = Math.abs(balance / TOTAL_DAYS);
if (TOTAL_DAYS_FOR_AVERAGE > 0) {
average = Math.abs(balance / TOTAL_DAYS_FOR_AVERAGE);
}
LimitLine average_line = new LimitLine(average);
average_line.setLabel(getString(R.string.average, getAverage(average)));

View File

@ -76,7 +76,7 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment {
@Override
protected String getBalanceMessage(long balance, int targetValue) {
if (balance > 0) {
final long totalBalance = balance - ((long)targetValue * TOTAL_DAYS);
final long totalBalance = balance - ((long)targetValue * TOTAL_DAYS_FOR_AVERAGE);
if (totalBalance > 0)
return getString(R.string.overslept, getHM(totalBalance));
else

View File

@ -109,7 +109,7 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment {
@Override
protected String getBalanceMessage(long balance, int targetValue) {
if (balance > 0) {
final long totalBalance = balance - ((long)targetValue * TOTAL_DAYS);
final long totalBalance = balance - ((long)targetValue * TOTAL_DAYS_FOR_AVERAGE);
if (totalBalance > 0)
return getString(R.string.overstep, Math.abs(totalBalance));
else

View File

@ -29,4 +29,8 @@ public class DeviceSettingsPreferenceConst {
public static final String PREF_BUTTON_2_FUNCTION = "button_2_function";
public static final String PREF_BUTTON_3_FUNCTION = "button_3_function";
public static final String PREF_VIBRATION_STRENGH_PERCENTAGE = "vibration_strength";
public static final String PREF_RELAX_FIRMWARE_CHECKS = "relax_firmware_checks";
public static final String PREF_HYBRID_HR_FORCE_WHITE_COLOR = "force_white_color_scheme";
public static final String PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES = "widget_draw_circles";
}

View File

@ -43,6 +43,8 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_2_FUNCTION;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_3_FUNCTION;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_FORCE_WHITE_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_ORIENTATION;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TIMEFORMAT;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE;
@ -322,6 +324,9 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat {
addPreferenceHandlerFor(PREF_BUTTON_3_FUNCTION);
addPreferenceHandlerFor(PREF_VIBRATION_STRENGH_PERCENTAGE);
addPreferenceHandlerFor(PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES);
addPreferenceHandlerFor(PREF_HYBRID_HR_FORCE_WHITE_COLOR);
String displayOnLiftState = prefs.getString(PREF_ACTIVATE_DISPLAY_ON_LIFT, PREF_DO_NOT_DISTURB_OFF);
boolean displayOnLiftScheduled = displayOnLiftState.equals(PREF_DO_NOT_DISTURB_SCHEDULED);

View File

@ -28,6 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
public abstract class HuamiFWHelper extends AbstractMiBandFWHelper {
protected HuamiFirmwareInfo firmwareInfo;
@ -110,6 +111,10 @@ public abstract class HuamiFWHelper extends AbstractMiBandFWHelper {
firmwareInfo.checkValid();
}
@Override
public HuamiFirmwareType getFirmwareType() {
return firmwareInfo.getFirmwareType();
}
public HuamiFirmwareInfo getFirmwareInfo() {
return firmwareInfo;
}

View File

@ -26,7 +26,9 @@ import androidx.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
@ -63,4 +65,21 @@ public class AmazfitBipLiteCoordinator extends AmazfitBipCoordinator {
public int getBondingStyle() {
return BONDING_STYLE_REQUIRE_KEY;
}
@Override
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[]{
R.xml.devicesettings_amazfitbip,
R.xml.devicesettings_timeformat,
R.xml.devicesettings_wearlocation,
R.xml.devicesettings_custom_emoji_font,
R.xml.devicesettings_liftwrist_display,
R.xml.devicesettings_disconnectnotification,
R.xml.devicesettings_sync_calendar,
R.xml.devicesettings_expose_hr_thirdparty,
R.xml.devicesettings_buttonactions_with_longpress,
R.xml.devicesettings_pairingkey,
R.xml.devicesettings_relax_firmware_checks,
};
}
}

View File

@ -0,0 +1,99 @@
/* Copyright (C) 2017-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele
Gobbetti, João Paulo Barraca, Nephiel, vanous
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.amazfitbips;
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.R;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class AmazfitBipSCoordinator extends HuamiCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AmazfitBipSCoordinator.class);
@Override
public DeviceType getDeviceType() {
return DeviceType.AMAZFITBIPS;
}
@NonNull
@Override
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
try {
BluetoothDevice device = candidate.getDevice();
String name = device.getName();
if (name != null && (name.equalsIgnoreCase("Amazfit Bip S"))) {
return DeviceType.AMAZFITBIPS;
}
} catch (Exception ex) {
LOG.error("unable to check device support", ex);
}
return DeviceType.UNKNOWN;
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
return null;
}
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return true;
}
@Override
public boolean supportsActivityTracks() {
return true;
}
@Override
public boolean supportsWeather() {
return true;
}
@Override
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[]{
R.xml.devicesettings_amazfitbip,
R.xml.devicesettings_timeformat,
R.xml.devicesettings_wearlocation,
R.xml.devicesettings_custom_emoji_font,
R.xml.devicesettings_liftwrist_display,
R.xml.devicesettings_disconnectnotification,
R.xml.devicesettings_sync_calendar,
R.xml.devicesettings_expose_hr_thirdparty,
R.xml.devicesettings_buttonactions_with_longpress,
R.xml.devicesettings_pairingkey
};
}
@Override
public int getBondingStyle() {
return BONDING_STYLE_REQUIRE_KEY;
}
}

View File

@ -22,7 +22,6 @@ import android.net.Uri;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWInstallHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -40,7 +39,7 @@ class AmazfitGTSFWInstallHandler extends AbstractMiBandFWInstallHandler {
@Override
protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException {
return new AmazfitGTRFWHelper(uri, context);
return new AmazfitGTSFWHelper(uri, context);
}
@Override

View File

@ -31,6 +31,7 @@ import androidx.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
@ -122,4 +123,6 @@ public abstract class AbstractMiBandFWHelper {
protected abstract void determineFirmwareInfo(byte[] wholeFirmwareBytes);
public abstract void checkValid() throws IllegalArgumentException;
public abstract HuamiFirmwareType getFirmwareType();
}

View File

@ -30,6 +30,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType.WATCHFACE;
public abstract class AbstractMiBandFWInstallHandler implements InstallHandler {
private static final Logger LOG = LoggerFactory.getLogger(AbstractMiBandFWInstallHandler.class);
@ -58,7 +60,7 @@ public abstract class AbstractMiBandFWInstallHandler implements InstallHandler {
protected abstract AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException;
protected GenericItem createInstallItem(GBDevice device) {
private GenericItem createInstallItem(GBDevice device) {
return new GenericItem(mContext.getString(R.string.installhandler_firmware_name, mContext.getString(device.getType().getName()), helper.getFirmwareKind(), helper.getHumanFirmwareVersion()));
}
@ -98,23 +100,25 @@ public abstract class AbstractMiBandFWInstallHandler implements InstallHandler {
return;
}
StringBuilder builder = new StringBuilder();
if (helper.isSingleFirmware()) {
getFwUpgradeNotice();
builder.append(getFwUpgradeNotice());
} else {
builder.append(mContext.getString(R.string.fw_multi_upgrade_notice, helper.getHumanFirmwareVersion(), helper.getHumanFirmwareVersion2()));
}
if (helper.getFirmwareType() != WATCHFACE) {
if (helper.isSingleFirmware()) {
getFwUpgradeNotice();
builder.append(getFwUpgradeNotice());
} else {
builder.append(mContext.getString(R.string.fw_multi_upgrade_notice, helper.getHumanFirmwareVersion(), helper.getHumanFirmwareVersion2()));
}
if (helper.isFirmwareWhitelisted()) {
builder.append(" ").append(mContext.getString(R.string.miband_firmware_known));
fwItem.setDetails(mContext.getString(R.string.miband_fwinstaller_compatible_version));
// TODO: set a CHECK (OKAY) button
} else {
builder.append(" ").append(mContext.getString(R.string.miband_firmware_unknown_warning)).append(" \n\n")
.append(mContext.getString(R.string.miband_firmware_suggest_whitelist, String.valueOf(helper.getFirmwareVersion())));
fwItem.setDetails(mContext.getString(R.string.miband_fwinstaller_untested_version));
// TODO: set a UNKNOWN (question mark) button
if (helper.isFirmwareWhitelisted()) {
builder.append(" ").append(mContext.getString(R.string.miband_firmware_known));
fwItem.setDetails(mContext.getString(R.string.miband_fwinstaller_compatible_version));
// TODO: set a CHECK (OKAY) button
} else {
builder.append(" ").append(mContext.getString(R.string.miband_firmware_unknown_warning)).append(" \n\n")
.append(mContext.getString(R.string.miband_firmware_suggest_whitelist, String.valueOf(helper.getFirmwareVersion())));
fwItem.setDetails(mContext.getString(R.string.miband_fwinstaller_untested_version));
// TODO: set a UNKNOWN (question mark) button
}
}
installActivity.setInfoText(builder.toString());
installActivity.setInstallItem(fwItem);

View File

@ -29,6 +29,7 @@ import androidx.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.AbstractMiFirmwareInfo;
/**
@ -122,6 +123,11 @@ public class MiBandFWHelper extends AbstractMiBandFWHelper {
firmwareInfo.checkValid();
}
@Override
public HuamiFirmwareType getFirmwareType() {
return null;
}
/**
* @param wholeFirmwareBytes
* @return

View File

@ -0,0 +1,111 @@
/* Copyright (C) 2020 Andreas Shimokawa
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.qhybrid;
import android.content.Context;
import android.net.Uri;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.InstallActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
public class FossilHRInstallHandler implements InstallHandler {
private final Context mContext;
private boolean mIsValid;
private String mVersion = "(Unknown version)";
FossilHRInstallHandler(Uri uri, Context context) {
mContext = context;
UriHelper uriHelper;
try {
uriHelper = UriHelper.get(uri, mContext);
} catch (IOException e) {
mIsValid = false;
return;
}
try (InputStream in = new BufferedInputStream(uriHelper.openInputStream())) {
byte[] bytes = new byte[32];
int read = in.read(bytes);
if (read < 32) {
mIsValid = false;
return;
}
ByteBuffer buf = ByteBuffer.wrap(bytes);
buf.order(ByteOrder.LITTLE_ENDIAN);
int header0 = buf.getInt();
buf.getInt(); // size
int header2 = buf.getInt();
int header3 = buf.getInt();
if (header0 != 1 || header2 != 0x00012000 || header3 != 0x00012000) {
mIsValid = false;
return;
}
buf.getInt(); // unknown
int version1 = buf.get() % 0xff;
int version2 = buf.get() & 0xff;
mVersion = "DN1.0." + version1 + "." + version2;
} catch (Exception e) {
mIsValid = false;
return;
}
mIsValid = true;
}
@Override
public void validateInstallation(InstallActivity installActivity, GBDevice device) {
if (device.isBusy()) {
installActivity.setInfoText(device.getBusyTask());
installActivity.setInstallEnabled(false);
return;
}
if (device.getType() != DeviceType.FOSSILQHYBRID || !device.isConnected()) {
installActivity.setInfoText("Element cannot be installed");
installActivity.setInstallEnabled(false);
return;
}
GenericItem installItem = new GenericItem();
installItem.setIcon(R.drawable.ic_firmware);
installItem.setName("Fossil Hybrid HR Firmware");
installItem.setDetails(mVersion);
installActivity.setInfoText(mContext.getString(R.string.firmware_install_warning, "(unknown)"));
installActivity.setInstallEnabled(true);
installActivity.setInstallItem(installItem);
}
@Override
public void onStartInstall(GBDevice device) {
}
@Override
public boolean isValid() {
return mIsValid;
}
}

View File

@ -1,10 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
@ -26,6 +30,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -53,6 +58,9 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
SparseArray<String> widgetButtonsMapping = new SparseArray<>(4);
static public final String CONFIG_KEY_Q_ACTIONS = "Q_ACTIONS";
private static final int REQUEST_CODE_WIDGET_EDIT = 0;
private static final int REQUEST_CODE_IMAGE_PICK = 1;
private static final int REQUEST_CODE_IMAGE_EDIT = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -84,7 +92,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
startIntent.putExtra("EXTRA_WIDGET", widget);
startIntent.putExtra("EXTRA_WIDGET_IDNEX", position);
startActivityForResult(startIntent, 0);
startActivityForResult(startIntent, REQUEST_CODE_WIDGET_EDIT);
}
});
loadCustomWidgetList();
@ -94,7 +102,36 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
public void onClick(View v) {
Intent startIntent = new Intent(HRConfigActivity.this, WidgetSettingsActivity.class);
startActivityForResult(startIntent, 0);
startActivityForResult(startIntent, REQUEST_CODE_WIDGET_EDIT);
}
});
findViewById(R.id.qhybrid_set_background).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new AlertDialog.Builder(HRConfigActivity.this)
.setTitle("whoop whoop")
.setMessage("background has to be pushed every time a custom widget changes, causing traffic and battery drain. Consider that when using custom widgets.")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent pickIntent = new Intent(Intent.ACTION_PICK);
pickIntent.setType("image/*");
startActivityForResult(pickIntent, REQUEST_CODE_IMAGE_PICK);
}
})
.setNegativeButton("nah", null)
.show();
}
});
findViewById(R.id.qhybrid_unset_background).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(QHybridSupport.QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
intent.putIntegerArrayListExtra("EXTRA_PIXELS", null);
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(intent);
}
});
@ -138,34 +175,50 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data == null) return;
if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_CREATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
this.customWidgets.add(widget);
refreshWidgetList();
saveCustomWidgetList();
if(requestCode == REQUEST_CODE_WIDGET_EDIT) {
if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_CREATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
this.customWidgets.add(widget);
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_UPDATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_UPDATED) {
CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
this.customWidgets.set(updateIndex, widget);
this.customWidgets.set(updateIndex, widget);
refreshWidgetList();
saveCustomWidgetList();
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED){
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
} else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED) {
int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
this.customWidgets.remove(updateIndex);
this.customWidgets.remove(updateIndex);
refreshWidgetList();
saveCustomWidgetList();
refreshWidgetList();
saveCustomWidgetList();
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
}
}else if(requestCode == REQUEST_CODE_IMAGE_PICK){
if (resultCode == RESULT_OK)
{
Uri imageUri = data.getData();
Intent activityIntent = new Intent();
activityIntent.setClass(this, ImageEditActivity.class);
activityIntent.setData(imageUri);
startActivityForResult(activityIntent, REQUEST_CODE_IMAGE_EDIT);
}
}else if(requestCode == REQUEST_CODE_IMAGE_EDIT){
if(resultCode == ImageEditActivity.RESULT_CODE_EDIT_SUCCESS){
data.setAction(QHybridSupport.QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(data);
}
}
}
private void saveCustomWidgetList() {
@ -474,6 +527,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
super(HRConfigActivity.this, 0, objects);
}
@SuppressLint("ResourceType")
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {

View File

@ -0,0 +1,75 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.List;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.HybridHRActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HybridHRActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry;
public class HybridHRActivitySampleProvider extends AbstractSampleProvider<HybridHRActivitySample> {
public HybridHRActivitySampleProvider(GBDevice device, DaoSession session) {
super(device, session);
}
@Override
public AbstractDao<HybridHRActivitySample, ?> getSampleDao() {
return getSession().getHybridHRActivitySampleDao();
}
@Nullable
@Override
protected Property getRawKindSampleProperty() {
return null;
}
@NonNull
@Override
protected Property getTimestampSampleProperty() {
return HybridHRActivitySampleDao.Properties.Timestamp;
}
@NonNull
@Override
protected Property getDeviceIdentifierSampleProperty() {
return HybridHRActivitySampleDao.Properties.DeviceId;
}
@Override
public int normalizeType(int rawType) {
if(rawType == -1) return 0;
return ActivityEntry.WEARING_STATE.fromValue((byte) rawType).getActivityKind();
}
@Override
public int toRawActivityKind(int activityKind) {
return 0;
}
@Override
public float normalizeIntensity(int rawIntensity) {
return rawIntensity / 63f;
}
@Override
public HybridHRActivitySample createActivitySample() {
return new HybridHRActivitySample();
}
@Override
public List<HybridHRActivitySample> getActivitySamples(int timestamp_from, int timestamp_to) {
return super.getActivitySamples(timestamp_from, timestamp_to);
}
@Override
public List<HybridHRActivitySample> getAllActivitySamples(int timestamp_from, int timestamp_to) {
return super.getAllActivitySamples(timestamp_from, timestamp_to);
}
}

View File

@ -0,0 +1,260 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class ImageEditActivity extends AbstractGBActivity implements View.OnTouchListener {
static final public int RESULT_CODE_EDIT_SUCCESS = 0;
ImageView overlay;
Canvas overlayCanvas;
Paint overlayPaint;
Bitmap overlayBitmap, mainBitmap;
float x = 0, y = 0, diameter = 0, imageDimension = 0;
int imageWidth, imageHeight;
private enum MovementState {
MOVE_UPPER_LEFT,
MOVE_LOWER_RIGHT,
MOVE_FRAME
}
private MovementState movementState;
float movementStartX, movementStartY, movementStartFrameX, movementStartFrameY, movementStartDiameter, leftUpperDeltaX, leftUpperDeltaY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qhybrid_image_edit);
final RelativeLayout mainLayout = findViewById(R.id.qhybrid_image_edit_container);
overlay = findViewById(R.id.qhybrid_image_edit_image_overlay);
overlay.setOnTouchListener(this);
findViewById(R.id.qhybrid_image_edit_okay).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finalizeImage();
}
});
mainLayout.post(new Runnable() {
@Override
public void run() {
try {
fitImageToLayout(mainLayout);
} catch (IOException | RuntimeException e) {
GB.log("Error formatting image", GB.ERROR, e);
GB.toast("Error formatting image", Toast.LENGTH_LONG, GB.ERROR);
finish();
}
}
});
}
private void finalizeImage(){
Bitmap cropped = Bitmap.createBitmap(this.mainBitmap, (int) this.x, (int) this.y, (int) this.diameter, (int) this.diameter);
Bitmap scaled = Bitmap.createScaledBitmap(cropped, 400, 400, false);
cropped.recycle();
try {
AssetImage image = AssetImageFactory.createAssetImage(scaled, false, 0, 0, 0);
Intent resultIntent = new Intent();
resultIntent.putExtra("EXTRA_PIXELS_ENCODED", image.getFileData());
setResult(RESULT_CODE_EDIT_SUCCESS, resultIntent);
finish();
} catch (IOException e) {
e.printStackTrace();
} finally {
scaled.recycle();
}
}
private void fitImageToLayout(RelativeLayout mainLayout) throws IOException, RuntimeException {
float containerHeight = mainLayout.getHeight();
float containerWidth = mainLayout.getWidth();
float containerRelation = containerHeight / containerWidth;
Bitmap bitmap = this.createImageFromURI();
float imageHeight = bitmap.getHeight();
float imageWidth = bitmap.getWidth();
float imageRelation = imageHeight / imageWidth;
float scaleRatio;
if(imageRelation > containerRelation){
scaleRatio = containerHeight / imageHeight;
}else{
scaleRatio = containerWidth / imageWidth;
}
int scaledHeight = (int)(imageHeight * scaleRatio);
int scaledWidth = (int)(imageWidth * scaleRatio);
this.imageHeight = scaledHeight;
this.imageWidth = scaledWidth;
this.imageDimension = this.diameter = Math.min(scaledHeight, scaledWidth);
mainBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, false);
ImageView mainImageView = findViewById(R.id.qhybrid_image_edit_image);
mainImageView.setImageBitmap(mainBitmap);
createOverlay(scaledWidth, scaledHeight);
}
private void createOverlay(int width, int height){
this.overlayBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
this.overlayCanvas = new Canvas(this.overlayBitmap);
this.overlayPaint = new Paint();
this.overlayPaint.setColor(Color.BLACK);
this.overlayPaint.setStyle(Paint.Style.STROKE);
this.overlayPaint.setStrokeWidth(imageDimension / 100);
renderOverlay();
}
private Bitmap createImageFromURI() throws IOException, RuntimeException {
Uri imageURI = getIntent().getData();
if (imageURI == null) {
throw new RuntimeException("no image attached");
}
ContentResolver resolver = getContentResolver();
Cursor c = resolver.query(imageURI, new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
c.moveToFirst();
int orientation = c.getInt(c.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
c.close();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageURI);
if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
}
private void renderOverlay() {
overlayCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
overlayCanvas.drawCircle(x, y, imageDimension / 15, overlayPaint);
overlayCanvas.drawCircle(x + diameter, y + diameter, imageDimension / 15, overlayPaint);
overlayCanvas.drawCircle(x + diameter / 2, y + diameter / 2, diameter / 2, overlayPaint);
overlay.setImageBitmap(overlayBitmap);
}
private void forceImageBoundaries(){
this.x = Math.max(this.x, 0);
this.y = Math.max(this.y, 0);
this.x = Math.min(this.x, this.imageWidth - diameter);
this.y = Math.min(this.y, this.imageHeight - diameter);
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
handleTouchDown(motionEvent);
}else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
handleTouchMove(motionEvent);
}
return true;
}
private void handleTouchMove(MotionEvent motionEvent){
if(movementState == MovementState.MOVE_UPPER_LEFT){
float moveDeltaX = motionEvent.getX() - this.movementStartX;
float moveDeltaY = motionEvent.getY() - this.movementStartY;
float mid = (moveDeltaX + moveDeltaY) / 2;
this.diameter = this.movementStartDiameter - mid;
this.x = this.movementStartX + mid + this.leftUpperDeltaX;
this.y = this.movementStartY + mid + this.leftUpperDeltaY;
}else if(movementState == MovementState.MOVE_LOWER_RIGHT) {
float moveDeltaX = motionEvent.getX() - this.movementStartX;
float moveDeltaY = motionEvent.getY() - this.movementStartY;
float mid = (moveDeltaX + moveDeltaY) / 2;
this.diameter = this.movementStartDiameter + mid;
}else if(movementState == MovementState.MOVE_FRAME){
this.x = this.movementStartFrameX + (motionEvent.getX() - this.movementStartX);
this.y = this.movementStartFrameY + (motionEvent.getY() - this.movementStartY);
}
this.forceImageBoundaries();
renderOverlay();
}
private void handleTouchDown(MotionEvent motionEvent) {
this.movementStartX = motionEvent.getX();
this.movementStartY = motionEvent.getY();
this.movementStartFrameX = this.x;
this.movementStartFrameY = this.y;
this.movementStartDiameter = this.diameter;
final float threshold = imageDimension / 15;
float upperLeftDeltaX = this.x - motionEvent.getX();
float upperLeftDeltaY = this.y - motionEvent.getY();
float upperLeftDistance = (float) Math.sqrt(upperLeftDeltaX * upperLeftDeltaX + upperLeftDeltaY * upperLeftDeltaY);
if(upperLeftDistance < threshold){
// Toast.makeText(this, "upper left", 0).show();
this.leftUpperDeltaX = upperLeftDeltaX;
this.leftUpperDeltaY = upperLeftDeltaY;
this.movementState = MovementState.MOVE_UPPER_LEFT;
return;
}
float lowerLeftX = this.x + diameter;
float lowerLeftY = this.y + diameter;
float lowerRightDeltaX = lowerLeftX - motionEvent.getX();
float lowerRightDeltaY = lowerLeftY - motionEvent.getY();
float lowerRightDistance = (float) Math.sqrt(lowerRightDeltaX * lowerRightDeltaX + lowerRightDeltaY * lowerRightDeltaY);
if(lowerRightDistance < threshold){
// Toast.makeText(this, "lower right", 0).show();
this.movementState = MovementState.MOVE_LOWER_RIGHT;
return;
}
// Toast.makeText(this, "anywhere else", 0).show();
this.movementState = MovementState.MOVE_FRAME;
}
}

View File

@ -79,12 +79,13 @@ public class QHybridCoordinator extends AbstractDeviceCoordinator {
@Override
public boolean supportsActivityDataFetching() {
return true;
GBDevice connectedDevice = GBApplication.app().getDeviceManager().getSelectedDevice();
return connectedDevice != null && connectedDevice.getType() == DeviceType.FOSSILQHYBRID && connectedDevice.getState() == GBDevice.State.INITIALIZED;
}
@Override
public boolean supportsActivityTracking() {
return false;
return true;
}
@Override
@ -94,11 +95,15 @@ public class QHybridCoordinator extends AbstractDeviceCoordinator {
@Override
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
return new HybridHRActivitySampleProvider(device, session);
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
if (isHybridHR()) {
FossilHRInstallHandler installHandler = new FossilHRInstallHandler(uri, context);
return installHandler.isValid() ? installHandler : null;
}
return null;
}
@ -127,7 +132,7 @@ public class QHybridCoordinator extends AbstractDeviceCoordinator {
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return false;
return this.isHybridHR();
}
@Override

View File

@ -7,6 +7,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;

View File

@ -0,0 +1,24 @@
package nodomain.freeyourgadget.gadgetbridge.entities;
public abstract class AbstractHybridHRActivitySample extends AbstractActivitySample {
abstract public int getCalories();
abstract public byte getWear_type();
@Override
public int getRawKind() {
return getWear_type();
}
@Override
public int getRawIntensity() {
return getCalories();
}
@Override
public void setUserId(long userId) {}
@Override
public long getUserId() {
return 0;
}
}

View File

@ -43,6 +43,7 @@ public enum DeviceType {
AMAZFITBIP_LITE(17, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_bip_lite),
AMAZFITGTR(18, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_gtr),
AMAZFITGTS(19, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_gts),
AMAZFITBIPS(20, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_bips),
LIVEVIEW(30, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_liveview),
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),

View File

@ -36,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.casiogb6900.CasioGB6
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipLiteSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgtr.AmazfitGTRSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor.AmazfitCorSupport;
@ -149,6 +150,9 @@ public class DeviceSupportFactory {
case AMAZFITBIP_LITE:
deviceSupport = new ServiceDeviceSupport(new AmazfitBipLiteSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case AMAZFITBIPS:
deviceSupport = new ServiceDeviceSupport(new AmazfitBipSSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case AMAZFITGTR:
deviceSupport = new ServiceDeviceSupport(new AmazfitGTRSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;

View File

@ -32,9 +32,10 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.SimpleTimeZone;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
@ -55,6 +56,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSuppo
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(BangleJSDeviceSupport.class);
@ -81,7 +83,10 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
builder.notify(rxCharacteristic, true);
uartTx(builder, " \u0003"); // clear active line
setTime(builder);
Prefs prefs = GBApplication.getPrefs();
if (prefs.getBoolean("datetime_synconconnect", true))
setTime(builder);
//sendSettings(builder);
// get version
@ -98,7 +103,7 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
private void uartTx(TransactionBuilder builder, String str) {
LOG.info("UART TX: " + str);
byte[] bytes;
bytes = str.getBytes(StandardCharsets.UTF_8);
bytes = str.getBytes(StandardCharsets.ISO_8859_1);
for (int i=0;i<bytes.length;i+=20) {
int l = bytes.length-i;
if (l>20) l=20;
@ -234,7 +239,15 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
void setTime(TransactionBuilder builder) {
uartTx(builder, "\u0010setTime("+(System.currentTimeMillis()/1000)+");E.setTimeZone("+(TimeZone.getDefault().getRawOffset()/3600000)+");\n");
long ts = System.currentTimeMillis();
float tz = SimpleTimeZone.getDefault().getOffset(ts) / (1000 * 60 * 60.0f);
// set time
String cmd = "\u0010setTime("+(ts/1000)+");";
// set timezone
cmd += "E.setTimeZone("+tz+");";
// write timezone to settings
cmd += "(s=>{s&&(s.timezone="+tz+")&&require('Storage').write('setting.json',s);})(require('Storage').readJSON('setting.json',1))";
uartTx(builder, cmd+"\n");
}
@Override

View File

@ -1928,7 +1928,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
buf.put((byte) 4);
buf.putInt(weatherSpec.timestamp);
buf.put((byte) (tz_offset_hours * 4));
buf.putShort((short) 0);
buf.putShort((short) -1);
if (supportsConditionString) {
buf.put(aqiString.getBytes());
buf.put((byte) 0);

View File

@ -19,11 +19,14 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip;
import java.util.HashMap;
import java.util.Map;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class AmazfitBipLiteFirmwareInfo extends HuamiFirmwareInfo {
@ -66,6 +69,15 @@ public class AmazfitBipLiteFirmwareInfo extends HuamiFirmwareInfo {
if (searchString32BitAligned(bytes, "Amazfit Bip Lite")) {
return HuamiFirmwareType.FIRMWARE;
}
GBDevice device = GBApplication.app().getDeviceManager().getSelectedDevice();
if (device != null) {
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()));
if (prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_RELAX_FIRMWARE_CHECKS, false)) {
if (searchString32BitAligned(bytes, "Amazfit Bip")) {
return HuamiFirmwareType.FIRMWARE;
}
}
}
return HuamiFirmwareType.INVALID;
}
if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER)) {

View File

@ -0,0 +1,48 @@
/* Copyright (C) 2017-2020 Andreas Shimokawa, Carsten Pfeiffer
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.amazfitbip;
import android.content.Context;
import android.net.Uri;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
public class AmazfitBipSSupport extends AmazfitBipSupport {
@Override
public byte getCryptFlags() {
return (byte) 0x80;
}
@Override
public void onNotification(NotificationSpec notificationSpec) {
super.sendNotificationNew(notificationSpec, true);
}
@Override
protected byte getAuthFlags() {
return 0x00;
}
@Override
public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException {
return null;
}
}

View File

@ -77,7 +77,7 @@ public class AmazfitGTRFirmwareInfo extends HuamiFirmwareInfo {
}
return HuamiFirmwareType.INVALID;
}
if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER)) {
if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER) || ArrayUtils.equals(bytes, WATCHFACE_HEADER, COMPRESSED_RES_HEADER_OFFSET_NEW) || ArrayUtils.equals(bytes, WATCHFACE_HEADER, COMPRESSED_RES_HEADER_OFFSET)) {
return HuamiFirmwareType.WATCHFACE;
}
if (ArrayUtils.startsWith(bytes, NEWFT_HEADER)) {

View File

@ -26,6 +26,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRF
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.UpdateFirmwareOperationNew;
public class AmazfitGTRSupport extends AmazfitBipSupport {
@ -49,6 +50,11 @@ public class AmazfitGTRSupport extends AmazfitBipSupport {
return new AmazfitGTRFWHelper(uri, context);
}
@Override
public UpdateFirmwareOperationNew createUpdateFirmwareOperation(Uri uri) {
return new UpdateFirmwareOperationNew(uri, this);
}
@Override
protected AmazfitGTRSupport setDisplayItems(TransactionBuilder builder) {
// not supported yet

View File

@ -77,7 +77,7 @@ public class AmazfitGTSFirmwareInfo extends HuamiFirmwareInfo {
}
return HuamiFirmwareType.INVALID;
}
if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER)) {
if (ArrayUtils.startsWith(bytes, WATCHFACE_HEADER) || ArrayUtils.equals(bytes, WATCHFACE_HEADER, COMPRESSED_RES_HEADER_OFFSET_NEW) || ArrayUtils.equals(bytes, WATCHFACE_HEADER, COMPRESSED_RES_HEADER_OFFSET)) {
return HuamiFirmwareType.WATCHFACE;
}
if (ArrayUtils.startsWith(bytes, NEWFT_HEADER)) {

View File

@ -22,11 +22,11 @@ import android.net.Uri;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRFWHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSFWHelper;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.UpdateFirmwareOperationNew;
public class AmazfitGTSSupport extends AmazfitBipSupport {
@ -51,6 +51,11 @@ public class AmazfitGTSSupport extends AmazfitBipSupport {
return new AmazfitGTSFWHelper(uri, context);
}
@Override
public UpdateFirmwareOperationNew createUpdateFirmwareOperation(Uri uri) {
return new UpdateFirmwareOperationNew(uri, this);
}
@Override
protected AmazfitGTSSupport setDisplayItems(TransactionBuilder builder) {
// not supported yet

View File

@ -89,6 +89,7 @@ public class QHybridSupport extends QHybridBaseSupport {
public static final String QHYBRID_COMMAND_SET_MENU_MESSAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_MESSAGE";
public static final String QHYBRID_COMMAND_SEND_MENU_ITEMS = "nodomain.freeyourgadget.gadgetbridge.Q_SEND_MENU_ITEMS";
public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT";
public static final String QHYBRID_COMMAND_SET_BACKGROUND_IMAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_BACKGROUND_IMAGE";
private static final String QHYBRID_ACTION_SET_ACTIVITY_HAND = "nodomain.freeyourgadget.gadgetbridge.Q_SET_ACTIVITY_HAND";
@ -144,6 +145,7 @@ public class QHybridSupport extends QHybridBaseSupport {
commandFilter.addAction(QHYBRID_COMMAND_NOTIFICATION_CONFIG_CHANGED);
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_WIDGETS);
commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS);
commandFilter.addAction(QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
commandReceiver = new BroadcastReceiver() {
@Override
@ -230,6 +232,11 @@ public class QHybridSupport extends QHybridBaseSupport {
watchAdapter.updateWidgets();
break;
}
case QHYBRID_COMMAND_SET_BACKGROUND_IMAGE:{
byte[] pixels = intent.getByteArrayExtra("EXTRA_PIXELS_ENCODED");
watchAdapter.setBackgroundImage(pixels);
break;
}
}
}
};
@ -534,6 +541,11 @@ public class QHybridSupport extends QHybridBaseSupport {
watchAdapter.onTestNewFunction();
}
@Override
public void onInstallApp(Uri uri) {
watchAdapter.onInstallApp(uri);
}
private void backupFile(DownloadFileRequest request) {
try {
File file = FileUtils.getExternalFile("qFiles/" + request.timeStamp);

View File

@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.net.Uri;
import java.util.ArrayList;
@ -63,6 +64,7 @@ public abstract class WatchAdapter {
public abstract void syncNotificationSettings();
public abstract void onTestNewFunction();
public abstract void setTimezoneOffsetMinutes(short offset);
public abstract void onInstallApp(Uri uri);
public abstract boolean supportsFindDevice();
public abstract boolean supportsExtendedVibration();
@ -130,4 +132,7 @@ public abstract class WatchAdapter {
public void onSendWeather(WeatherSpec weatherSpec) {
}
public void setBackgroundImage(byte[] pixels) {
}
}

View File

@ -20,6 +20,7 @@ import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.widget.Toast;
@ -382,6 +383,11 @@ public class FossilWatchAdapter extends WatchAdapter {
});
}
@Override
public void onInstallApp(Uri uri) {
}
@Override
public boolean supportsFindDevice() {
return false;

View File

@ -8,14 +8,21 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Build;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.BufferOverflowException;
import java.util.ArrayList;
import java.util.Calendar;
@ -27,11 +34,15 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HybridHRActivitySampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
import nodomain.freeyourgadget.gadgetbridge.entities.HybridHRActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
@ -42,9 +53,13 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityFileParser;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest;
@ -52,6 +67,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FirmwareFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.ImagesSetRequest;
@ -66,9 +83,11 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.Widget;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.WidgetsPutRequest;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.MUSIC_PHONE_REQUEST;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.MUSIC_WATCH_REQUEST;
@ -138,30 +157,63 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
queueWrite(new ConfigurationPutRequest(new nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.VibrationStrengthConfigItem((byte) strength), this));
}
private void loadNotificationConfigurations(){
private void loadNotificationConfigurations() {
this.notificationConfigurations = new NotificationHRConfiguration[]{
new NotificationHRConfiguration("generic", 0),
new NotificationHRConfiguration("call", new byte[]{(byte)0x80, (byte) 0x00, (byte) 0x59, (byte) 0xB7}, 0)
new NotificationHRConfiguration("call", new byte[]{(byte) 0x80, (byte) 0x00, (byte) 0x59, (byte) 0xB7}, 0)
};
}
private void loadBackground(){
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDeviceSupport().getDevice().getAddress()));
boolean forceWhiteBackground = prefs.getBoolean("force_white_color_scheme", false);
if (forceWhiteBackground) {
byte[] whiteGIF = new byte[]{
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, 0x01, 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3B
};
private File getBackgroundFile() {
return new File(getContext().getExternalFilesDir(null), "hr_background.bin");
}
Bitmap backgroundBitmap = BitmapFactory.decodeByteArray(whiteGIF, 0, whiteGIF.length);
//Bitmap backgroundBitmap = BitmapFactory.decodeFile("/sdcard/DCIM/Camera/IMG_20191129_200726.jpg");
private void loadBackground() {
this.backGroundImage = null;
try {
FileInputStream fis = new FileInputStream(getBackgroundFile());
int count = fis.available();
if (count != 14400) {
throw new RuntimeException("wrong background file length");
}
byte[] file = new byte[14400];
fis.read(file);
fis.close();
this.backGroundImage = AssetImageFactory.createAssetImage(file, 0, 0, 0);
} catch (FileNotFoundException e) {
SharedPreferences preferences = getDeviceSpecificPreferences();
if (preferences.getBoolean("force_white_color_scheme", false)) {
Bitmap whiteBitmap = Bitmap.createBitmap(239, 239, Bitmap.Config.ARGB_8888);
new Canvas(whiteBitmap).drawColor(Color.WHITE);
try {
this.backGroundImage = AssetImageFactory.createAssetImage(whiteBitmap, true, 0, 1, 0);
} catch (IOException e2) {
logger.error("Backgroundimage error", e2);
}
}
} catch (IOException | RuntimeException e) {
GB.log("error opening background file", GB.ERROR, e);
GB.toast("error opening background file", Toast.LENGTH_LONG, GB.ERROR);
}
}
@Override
public void setBackgroundImage(byte[] pixels) {
if (pixels == null) {
getBackgroundFile().delete();
loadBackground(); // recreates the white background in force-white mode, else backgroundImage=null
} else {
this.backGroundImage = AssetImageFactory.createAssetImage(pixels, 0, 0, 0);
try {
this.backGroundImage = AssetImageFactory.createAssetImage(backgroundBitmap, false, 0, 0, 0);
FileOutputStream fos = new FileOutputStream(getBackgroundFile(), false);
fos.write(pixels);
} catch (IOException e) {
logger.error("Backgroundimage error", e);
GB.log("error saving background", GB.ERROR, e);
GB.toast("error persistent saving background", Toast.LENGTH_LONG, GB.ERROR);
}
}
renderWidgets();
}
private void loadWidgets() {
@ -184,19 +236,22 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
positionMap.put("bottom", 180);
positionMap.put("left", 270);
while(keyIterator.hasNext()){
while (keyIterator.hasNext()) {
String position = keyIterator.next();
String identifier = widgetConfig.getString(position);
Widget.WidgetType type = Widget.WidgetType.fromJsonIdentifier(identifier);
Widget widget = null;
if(type != null) {
if (type != null) {
widget = new Widget(type, positionMap.get(position), 63, fontColor);
}else{
} else {
identifier = identifier.substring(7);
for(int i = 0; i < customWidgets.length(); i++){
for (int i = 0; i < customWidgets.length(); i++) {
JSONObject customWidget = customWidgets.getJSONObject(i);
if(customWidget.getString("name").equals(identifier)){
if (customWidget.getString("name").equals(identifier)) {
boolean drawCircle = false;
if (customWidget.has("drawCircle"))
drawCircle = customWidget.getBoolean("drawCircle");
CustomWidget newWidget = new CustomWidget(
customWidget.getString("name"),
positionMap.get(position),
@ -226,7 +281,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
}
}
if(widget == null) continue;
if (widget == null) continue;
this.widgets.add(widget);
}
} catch (JSONException e) {
@ -236,11 +291,11 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
uploadWidgets();
}
private void uploadWidgets(){
private void uploadWidgets() {
negotiateSymmetricKey();
ArrayList<Widget> systemWidgets = new ArrayList<>(widgets.size());
for(Widget widget : this.widgets){
if(!(widget instanceof CustomWidget)) systemWidgets.add(widget);
for (Widget widget : this.widgets) {
if (!(widget instanceof CustomWidget)) systemWidgets.add(widget);
}
queueWrite(new WidgetsPutRequest(systemWidgets.toArray(new Widget[0]), this));
}
@ -248,48 +303,68 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
private void renderWidgets() {
Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDeviceSupport().getDevice().getAddress()));
boolean forceWhiteBackground = prefs.getBoolean("force_white_color_scheme", false);
boolean drawCircles = prefs.getBoolean("widget_draw_circles", false);
Bitmap circleBitmap = null;
if (drawCircles) {
circleBitmap = Bitmap.createBitmap(76, 76, Bitmap.Config.ARGB_8888);
Canvas circleCanvas = new Canvas(circleBitmap);
Paint circlePaint = new Paint();
circlePaint.setAntiAlias(true);
circlePaint.setColor(forceWhiteBackground ? Color.WHITE : Color.BLACK);
circlePaint.setStyle(Paint.Style.FILL);
circlePaint.setStrokeWidth(3);
circleCanvas.drawCircle(38, 38, 35, circlePaint);
circlePaint.setColor(forceWhiteBackground ? Color.BLACK : Color.WHITE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(3);
circleCanvas.drawCircle(38, 38, 35, circlePaint);
}
try {
ArrayList<AssetImage> widgetImages = new ArrayList<>();
if(this.backGroundImage != null){
if (this.backGroundImage != null) {
widgetImages.add(this.backGroundImage);
}
for (int i = 0; i < this.widgets.size(); i++) {
Widget w = widgets.get(i);
if(!(w instanceof CustomWidget)) continue;
if (!(w instanceof CustomWidget)) {
if (drawCircles) {
widgetImages.add(AssetImageFactory.createAssetImage(
circleBitmap,
true,
w.getAngle(),
w.getDistance(),
1
));
}
continue;
}
;
CustomWidget widget = (CustomWidget) w;
Bitmap widgetBitmap = Bitmap.createBitmap(76, 76, Bitmap.Config.ARGB_8888);
Canvas widgetCanvas = new Canvas(widgetBitmap);
boolean backgroundDrawn = false;
Paint circlePaint = new Paint();
if(!backgroundDrawn){
circlePaint.setColor(forceWhiteBackground ? Color.WHITE : Color.BLACK);
circlePaint.setStyle(Paint.Style.FILL);
circlePaint.setStrokeWidth(3);
widgetCanvas.drawCircle(38, 38, 37, circlePaint);
circlePaint.setColor(forceWhiteBackground ? Color.BLACK : Color.WHITE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(3);
widgetCanvas.drawCircle(38, 38, 37, circlePaint);
if (drawCircles) {
widgetCanvas.drawBitmap(circleBitmap, 0, 0, null);
}
for (CustomWidgetElement element : widget.getElements()) {
if (element.getWidgetElementType() == CustomWidgetElement.WidgetElementType.TYPE_BACKGROUND) {
File imageFile = new File(element.getValue());
if(!imageFile.exists() || !imageFile.isFile()){
if (!imageFile.exists() || !imageFile.isFile()) {
logger.debug("Image file " + element.getValue() + " not found");
continue;
}
Bitmap imageBitmap = BitmapFactory.decodeFile(element.getValue());
if(imageBitmap == null){
if (imageBitmap == null) {
logger.debug("image file " + element.getValue() + " could not be decoded");
continue;
}
@ -300,7 +375,6 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
0,
0,
null);
backgroundDrawn = true;
break;
}
}
@ -315,7 +389,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
textPaint.setTextAlign(Paint.Align.CENTER);
widgetCanvas.drawText(element.getValue(), element.getX(), element.getY() - (textPaint.descent() + textPaint.ascent()) / 2f, textPaint);
}else if(element.getWidgetElementType() == CustomWidgetElement.WidgetElementType.TYPE_IMAGE) {
} else if (element.getWidgetElementType() == CustomWidgetElement.WidgetElementType.TYPE_IMAGE) {
Bitmap imageBitmap = BitmapFactory.decodeFile(element.getValue());
widgetCanvas.drawBitmap(imageBitmap, element.getX() - imageBitmap.getWidth() / 2f, element.getY() - imageBitmap.getHeight() / 2f, null);
@ -330,15 +404,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
));
}
AssetImage[] images = widgetImages.toArray(new AssetImage[0]);
// queueWrite(new FileDeleteRequest((short) 0x0700));
queueWrite(new AssetFilePutRequest(
images,
(byte) 0x00,
this
));
// queueWrite(new FileDeleteRequest((short) 0x0503));
queueWrite(new ImagesSetRequest(
images,
@ -353,8 +426,8 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) {
boolean update = false;
for (Widget widget : this.widgets) {
if(!(widget instanceof CustomWidget)) continue;
if(((CustomWidget) widget).updateElementValue(widgetID, content)) update = true;
if (!(widget instanceof CustomWidget)) continue;
if (((CustomWidget) widget).updateElementValue(widgetID, content)) update = true;
}
if (renderOnWatch && update) renderWidgets();
@ -401,7 +474,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
musicSpec.track,
this
));
}catch (BufferOverflowException e){
} catch (BufferOverflowException e) {
GB.log("musicInfo: " + musicSpec, GB.ERROR, e);
}
}
@ -424,6 +497,66 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override
public void onFetchActivityData() {
syncSettings();
queueWrite(new VerifyPrivateKeyRequest(this.getSecretKey(), this));
queueWrite(new FileLookupRequest((byte) 0x01, this){
@Override
public void handleFileLookup(final short fileHandle) {
queueWrite(new FileEncryptedGetRequest(fileHandle, FossilHRWatchAdapter.this) {
@Override
public void handleFileData(byte[] fileData) {
try (DBHandler dbHandler = GBApplication.acquireDB()) {
ActivityFileParser parser = new ActivityFileParser();
ArrayList<ActivityEntry> entries = parser.parseFile(fileData);
HybridHRActivitySampleProvider provider = new HybridHRActivitySampleProvider(getDeviceSupport().getDevice(), dbHandler.getDaoSession());
HybridHRActivitySample[] samples = new HybridHRActivitySample[entries.size()];
Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId();
Long deviceId = DBHelper.getDevice(getDeviceSupport(). getDevice(), dbHandler.getDaoSession()).getId();
for(int i = 0; i < entries.size(); i++){
samples[i] = entries.get(i).toDAOActivitySample(userId, deviceId);
}
provider.addGBActivitySamples(samples);
writeFile(String.valueOf(System.currentTimeMillis()), fileData);
queueWrite(new FileDeleteRequest(fileHandle));
GB.toast("synced activity data", Toast.LENGTH_SHORT, GB.INFO);
} catch (Exception ex) {
GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext());
}
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
}
});
}
@Override
public void handleFileLookupError(FILE_LOOKUP_ERROR error) {
if(error == FILE_LOOKUP_ERROR.FILE_EMPTY){
GB.toast("activity file empty yet", Toast.LENGTH_LONG, GB.ERROR);
}else{
throw new RuntimeException("strange lookup stuff");
}
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
}
});
}
private void writeFile(String fileName, byte[] value){
File activityDir = new File(getContext().getExternalFilesDir(null), "activity_hr");
activityDir.mkdir();
File f = new File(activityDir, fileName);
try {
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(value);
fos.close();
GB.toast("saved file data", Toast.LENGTH_SHORT, GB.INFO);
} catch (IOException e) {
GB.log("file error", GB.ERROR, e);
}
}
private void syncSettings() {
@ -441,14 +574,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
String senderOrTitle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title);
try {
for (NotificationHRConfiguration configuration : this.notificationConfigurations){
if(configuration.getPackageName().equals(notificationSpec.sourceAppId)){
for (NotificationHRConfiguration configuration : this.notificationConfigurations) {
if (configuration.getPackageName().equals(notificationSpec.sourceAppId)) {
queueWrite(new PlayTextNotificationRequest(notificationSpec.sourceAppId, senderOrTitle, notificationSpec.body, this));
return true;
}
}
queueWrite(new PlayTextNotificationRequest("generic", senderOrTitle, notificationSpec.body, this));
}catch (Exception e){
} catch (Exception e) {
e.printStackTrace();
}
return true;
@ -456,14 +589,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override
public void onFindDevice(boolean start) {
if(start){
if (start) {
new TransactionBuilder("vibrate find")
.write(
getDeviceSupport().getCharacteristic(UUID.fromString("3dda0005-957f-7d4a-34a6-74696673696d")),
new byte[]{(byte) 0x01, (byte) 0x04, (byte) 0x30, (byte) 0x75, (byte) 0x00, (byte) 0x00}
)
)
.queue(getDeviceSupport().getQueue());
}else{
} else {
new TransactionBuilder("vibrate find")
.write(
getDeviceSupport().getCharacteristic(UUID.fromString("3dda0005-957f-7d4a-34a6-74696673696d")),
@ -606,35 +739,48 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
}
}
// this was used to enumerate the weather icons :)
/*
static int i = 0;
@Override
public void onTestNewFunction() {
long ts = System.currentTimeMillis();
ts /= 1000;
/*queueWrite(new ActivityFilesGetRequest(this){
@Override
public void handleFileData(byte[] fileData) {
super.handleFileData(fileData);
File activityDir = new File(getContext().getExternalFilesDir(null), "activity_hr");
activityDir.mkdir();
File f = new File(activityDir, String.valueOf(System.currentTimeMillis()));
try {
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(fileData);
fos.close();
GB.toast("saved file data", Toast.LENGTH_SHORT, GB.INFO);
} catch (IOException e) {
GB.log("activity file error", GB.ERROR, e);
}
queueWrite(new FileDeleteRequest((short) 0x0101));
}
});*/
}
@Override
public void onInstallApp(Uri uri) {
UriHelper uriHelper = null;
try {
JSONObject responseObject = new JSONObject()
.put("res", new JSONObject()
.put("id", 0) // seems the id does not matter?
.put("set", new JSONObject()
.put("weatherInfo", new JSONObject()
.put("alive", ts + 60 * 60)
.put("unit", "c")
.put("temp", i)
.put("cond_id", i++)
)
));
queueWrite(new JsonPutRequest(responseObject, this));
} catch (JSONException e) {
logger.error(" JSON exception: ", e);
uriHelper = UriHelper.get(uri, getContext());
} catch (IOException e) {
GB.toast(getContext(), "Could not open firmare: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
}
if (uriHelper != null) {
try (InputStream in = new BufferedInputStream(uriHelper.openInputStream())) {
byte[] firmwareBytes = FileUtils.readAll(in, 1024 * 2024); // 2MB
queueWrite(new FirmwareFilePutRequest(firmwareBytes, this));
} catch (Exception e) {
GB.toast(getContext(), "Firmware cannot be installed: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
}
}
}
*/
public byte[] getSecretKey() {
byte[] authKeyBytes = new byte[16];
@ -704,6 +850,14 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
break;
case DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE:
setVibrationStrength();
break;
case "force_white_color_scheme":
loadBackground();
// not break here
case "widget_draw_circles": {
renderWidgets();
break;
}
}
}
@ -726,9 +880,9 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
byte requestType = value[1];
if(requestType == (byte) 0x04){
if (requestType == (byte) 0x04) {
handleCallRequest(value);
}else if (requestType == (byte) 0x05) {
} else if (requestType == (byte) 0x05) {
handleMusicRequest(value);
} else if (requestType == (byte) 0x01) {
int eventId = value[2];

View File

@ -19,7 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.mis
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Intent;
import android.util.Log;
import android.net.Uri;
import android.util.SparseArray;
import android.widget.Toast;
@ -49,6 +49,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ActivityPointGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.BatteryLevelRequest;
@ -66,7 +67,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mis
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.OTAEraseRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ReleaseHandsControlRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.RequestHandControlRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetCurrentStepCountRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetStepGoalRequest;
@ -418,6 +418,11 @@ public class MisfitWatchAdapter extends WatchAdapter {
GB.toast("old firmware does't support timezones", Toast.LENGTH_LONG, GB.ERROR);
}
@Override
public void onInstallApp(Uri uri) {
}
@Override
public boolean supportsFindDevice() {
return supportsExtendedVibration();

View File

@ -0,0 +1,65 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.entities.HybridHRActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class ActivityEntry {
public int id;
public int heartRate;
public int variability, maxVariability;
public int calories;
public int stepCount;
public boolean isActive;
public int timestamp;
public int heartRateQuality;
public WEARING_STATE wearingState;
public HybridHRActivitySample toDAOActivitySample(long userId, long deviceId) {
HybridHRActivitySample sample = new HybridHRActivitySample(
timestamp,
deviceId,
userId,
stepCount,
calories,
variability,
maxVariability,
heartRateQuality,
isActive,
wearingState.value,
heartRate
);
return sample;
}
public enum WEARING_STATE{
WEARING((byte) 0, ActivityKind.TYPE_NOT_MEASURED),
NOT_WEARING((byte) 1, ActivityKind.TYPE_NOT_WORN),
UNKNOWN((byte) 2, ActivityKind.TYPE_UNKNOWN);
byte value;
int activityKind;
WEARING_STATE(byte value, int activityKind){
this.value = value;
this.activityKind = activityKind;
}
public int getActivityKind() {
return activityKind;
}
static public WEARING_STATE fromValue(byte value){
switch (value){
case 0: return WEARING_STATE.WEARING;
case 1: return WEARING_STATE.NOT_WEARING;
case 2: return WEARING_STATE.UNKNOWN;
default: throw new RuntimeException("value " + value + " not valid state value");
}
}
}
}

View File

@ -0,0 +1,136 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
public class ActivityFileParser {
// state flags;
int heartRateQuality;
ActivityEntry.WEARING_STATE wearingState = ActivityEntry.WEARING_STATE.UNKNOWN;
int currentTimestamp = -1;
ActivityEntry currentSample = null;
int currentId = 1;
public ArrayList<ActivityEntry> parseFile(byte[] file) {
ByteBuffer buffer = ByteBuffer.wrap(file);
buffer.order(ByteOrder.LITTLE_ENDIAN);
// read file version
short version = buffer.getShort(2);
if (version != 22) throw new RuntimeException("File version " + version + ", 16 required");
int startTime = buffer.getInt(8);
short timeOffsetMinutes = buffer.getShort(12);
short fileId = buffer.getShort(16);
buffer.position(20);
ArrayList<ActivityEntry> samples = new ArrayList<>();
finishCurrentPacket(samples);
while (buffer.position() < buffer.capacity() - 4) {
byte next = buffer.get();
if (paraseFlag(next, buffer, samples)) continue;
if(currentSample != null) {
parseVariabilityBytes(next, buffer.get());
int heartRate = buffer.get() & 0xFF;
int calories = buffer.get() & 0xFF;
boolean isActive = (calories & 0x40) == 0x40; // upper two bits
calories &= 0x3F; // delete upper two bits
currentSample.heartRate = heartRate;
currentSample.calories = calories;
currentSample.isActive = isActive;
finishCurrentPacket(samples);
}
}
return samples;
}
private boolean paraseFlag(byte flag, ByteBuffer buffer, ArrayList<ActivityEntry> samples) {
switch (flag) {
case (byte) 0xCA:
case (byte) 0xCB:
case (byte) 0xCC:
case (byte) 0xCD:
buffer.get();
break;
case (byte) 0xCE:
byte arg = buffer.get();
byte wearBits = (byte)((arg & 0b00011000) >> 3);
if(wearBits == 0) this.wearingState = ActivityEntry.WEARING_STATE.NOT_WEARING;
else if(wearBits == 1) this.wearingState = ActivityEntry.WEARING_STATE.WEARING;
else this.wearingState = ActivityEntry.WEARING_STATE.UNKNOWN;
byte heartRateQualityBits = (byte)((arg & 0b11100000) >> 5);
this.heartRateQuality = heartRateQualityBits;
break;
case (byte) 0xCF:
case (byte) 0xDE:
case (byte) 0xDF:
case (byte) 0xE1:
buffer.get();
break;
case (byte) 0xE2:
byte type = buffer.get();
int timestamp = buffer.getInt();
short duration = buffer.getShort();
short minutesOffset = buffer.getShort();
if (type == 0x04) {
this.currentTimestamp = timestamp;
}
break;
case (byte) 0xDD:
case (byte) 0xFD:
buffer.get();
break;
case (byte) 0xFE:
byte arg2 = buffer.get();
if(arg2 == (byte) 0xFE) {
// this.currentSample = new ActivitySample();
// this.currentSample.id = currentId++;
}
break;
default:
return false;
}
return true;
}
private void parseVariabilityBytes(byte lower, byte higher){
if((lower & 0b0000001) == 0b0000001){
currentSample.maxVariability = (higher & 0b00000011) * 25 + 1;
currentSample.stepCount = lower & 0b1110;
if((lower & 0b10000000) == 0b10000000){
int factor = (lower >> 4) & 0b111;
currentSample.variability = 512 + factor * 64 + (higher >> 2 & 0b111111);
currentSample.stepCount = lower & 0b1110;
}else {
currentSample.variability = lower & 0b01110000;
currentSample.variability <<= 2;
currentSample.variability |= (higher >> 2) & 0b111111;
}
}else{
currentSample.variability = (int) higher * (int) higher * 64;
currentSample.maxVariability = 10000;
}
}
private void finishCurrentPacket(ArrayList<ActivityEntry> samples) {
if (currentSample != null) {
currentSample.timestamp = currentTimestamp;
currentSample.heartRateQuality = this.heartRateQuality;
currentSample.wearingState = wearingState;
currentTimestamp += 60;
samples.add(currentSample);
currentSample = null;
}
this.currentSample = new ActivityEntry();
this.currentSample.id = currentId++;
}
}

View File

@ -16,12 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.alarm;
import android.widget.Toast;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupAndGetRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class AlarmsGetRequest extends FileLookupAndGetRequest {
public AlarmsGetRequest(FossilWatchAdapter adapter) {
@ -59,4 +62,13 @@ public class AlarmsGetRequest extends FileLookupAndGetRequest {
alarms2[i] = Alarm.fromBytes(alarms[i].getData());
}
}
@Override
public void handleFileLookupError(FILE_LOOKUP_ERROR error) {
if(error == FILE_LOOKUP_ERROR.FILE_EMPTY){
GB.toast("alarm file empty yet", Toast.LENGTH_LONG, GB.ERROR);
}else{
throw new RuntimeException("strange lookup stuff");
}
}
}

View File

@ -20,17 +20,14 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.ResultCode;
public class FileLookupRequest extends FossilRequest {
public abstract class FileLookupRequest extends FossilRequest {
private short handle = -1;
private byte fileType;
@ -91,6 +88,11 @@ public class FileLookupRequest extends FossilRequest {
// throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
log("file size: " + size);
if(size == 0){
this.handleFileLookupError(FILE_LOOKUP_ERROR.FILE_EMPTY);
finished = true;
return;
}
fileBuffer = ByteBuffer.allocate(size);
}else if((first & 0x0F) == 8){
this.finished = true;
@ -122,7 +124,9 @@ public class FileLookupRequest extends FossilRequest {
}
}
public void handleFileLookup(short fileHandle){}
public abstract void handleFileLookup(short fileHandle);
public abstract void handleFileLookupError(FILE_LOOKUP_ERROR error);
@Override
public UUID getRequestUUID() {
@ -138,4 +142,8 @@ public class FileLookupRequest extends FossilRequest {
public int getPayloadLength() {
return 3;
}
public enum FILE_LOOKUP_ERROR{
FILE_EMPTY;
}
}

View File

@ -6,9 +6,11 @@ import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class PlayCallNotificationRequest extends PlayNotificationRequest {
private final static int MESSAGE_ID_CALL = 1;
public PlayCallNotificationRequest(String number, boolean callStart, FossilWatchAdapter adapter) {
super(callStart ? 1 : 7, callStart ? 8 : 2,
ByteBuffer.wrap(new byte[]{(byte) 0x80, (byte) 0x00, (byte) 0x59, (byte) 0xB7}).order(ByteOrder.LITTLE_ENDIAN).getInt(),
number, "Incoming Call", adapter);
number, "Incoming Call", MESSAGE_ID_CALL, adapter);
}
}

View File

@ -28,24 +28,28 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public abstract class PlayNotificationRequest extends FilePutRequest {
public PlayNotificationRequest(int notificationType, int flags, String packageName, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, packageName, packageName, packageName), adapter);
super((short) 0x0900, createFile(notificationType, flags, packageName, packageName, packageName, getCurrentMessageId()), adapter);
}
public PlayNotificationRequest(int notificationType, int flags, String packageName, String sender, String message, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, packageName, sender, message), adapter);
super((short) 0x0900, createFile(notificationType, flags, packageName, sender, message, getCurrentMessageId()), adapter);
}
public PlayNotificationRequest(int notificationType, int flags, int packageCRC, String sender, String message, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, "whatever", sender, message, packageCRC), adapter);
public PlayNotificationRequest(int notificationType, int flags, int packageCRC, String sender, String message, int messageId, FossilWatchAdapter adapter) {
super((short) 0x0900, createFile(notificationType, flags, "whatever", sender, message, packageCRC, messageId), adapter);
}
private static byte[] createFile(int notificationType, int flags, String packageName, String sender, String message){
private static int getCurrentMessageId(){
return (int) System.currentTimeMillis();
}
private static byte[] createFile(int notificationType, int flags, String packageName, String sender, String message, int messageId){
CRC32 crc = new CRC32();
crc.update(packageName.getBytes());
return createFile(notificationType, flags, packageName, sender, message, (int)crc.getValue());
return createFile(notificationType, flags, packageName, sender, message, (int)crc.getValue(), messageId);
}
private static byte[] createFile(int notificationType, int flags, String title, String sender, String message, int packageCrc) {
private static byte[] createFile(int notificationType, int flags, String title, String sender, String message, int packageCrc, int messageId) {
byte lengthBufferLength = (byte) 10;
byte uidLength = (byte) 4;
byte appBundleCRCLength = (byte) 4;
@ -59,7 +63,7 @@ public abstract class PlayNotificationRequest extends FilePutRequest {
String nullTerminatedMessage = StringUtils.terminateNull(message);
byte[] messageBytes = nullTerminatedMessage.getBytes(charsetUTF8);
if (messageBytes.length > 490) {
messageBytes = Arrays.copyOf(messageBytes, 490);
messageBytes = Arrays.copyOf(messageBytes, 475);
}
short mainBufferLength = (short) (lengthBufferLength + uidLength + appBundleCRCLength + titleBytes.length + senderBytes.length + messageBytes.length);
@ -77,7 +81,7 @@ public abstract class PlayNotificationRequest extends FilePutRequest {
mainBuffer.put((byte) senderBytes.length);
mainBuffer.put((byte) messageBytes.length);
mainBuffer.putInt(0); // messageId
mainBuffer.putInt(messageId);
mainBuffer.putInt(packageCrc);
mainBuffer.put(titleBytes);
mainBuffer.put(senderBytes);

View File

@ -0,0 +1,15 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.activity;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest;
public class ActivityFilesGetRequest extends FileEncryptedGetRequest {
public ActivityFilesGetRequest(FossilHRWatchAdapter adapter) {
super((short) 0x0101, adapter);
}
@Override
public void handleFileData(byte[] fileData) {
assert Boolean.TRUE;
}
}

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration;
import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
@ -54,4 +56,13 @@ public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
device.sendDeviceUpdateIntent(getAdapter().getContext());
}
@Override
public void handleFileLookupError(FILE_LOOKUP_ERROR error) {
if(error == FILE_LOOKUP_ERROR.FILE_EMPTY){
GB.toast("config file empty", Toast.LENGTH_LONG, GB.ERROR);
}else{
throw new RuntimeException("strange lookup stuff");
}
}
}

View File

@ -18,15 +18,10 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fo
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedPutRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.ConfigItem;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedPutRequest;
public class ConfigurationPutRequest extends FileEncryptedPutRequest {
public ConfigurationPutRequest(ConfigItem item, FossilHRWatchAdapter adapter) {

View File

@ -12,16 +12,16 @@ public class AssetFilePutRequest extends FilePutRequest {
public AssetFilePutRequest(AssetFile[] files, byte subHandle, FossilWatchAdapter adapter) throws IOException {
super((short) (0x0700 | subHandle), prepareFileData(files), adapter);
}
public AssetFilePutRequest(AssetFile file, byte subHandle, FossilWatchAdapter adapter) throws IOException {
public AssetFilePutRequest(AssetFile file, byte subHandle, FossilWatchAdapter adapter) {
super((short) (0x0700 | subHandle), prepareFileData(file), adapter);
}
private static byte[] prepareFileData(AssetFile[] files) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
for(int i = 0; i < files.length; i++){
for (AssetFile file : files) {
stream.write(
prepareFileData(files[i])
prepareFileData(file)
);
}
@ -29,7 +29,7 @@ public class AssetFilePutRequest extends FilePutRequest {
}
private static byte[] prepareFileData(AssetFile file){
int size = file.getFileName().length() + file.getFileData().length + 1 /**null byte **/;
int size = file.getFileName().length() + file.getFileData().length + 1; // null byte
ByteBuffer buffer = ByteBuffer.allocate(size + 2);
buffer.order(ByteOrder.LITTLE_ENDIAN);

View File

@ -23,7 +23,6 @@ import java.nio.ByteOrder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
@ -34,11 +33,10 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
import nodomain.freeyourgadget.gadgetbridge.util.CRC32C;
public abstract class FileEncryptedGetRequest extends FossilRequest {
private short handle;
@ -50,6 +48,10 @@ public abstract class FileEncryptedGetRequest extends FossilRequest {
private boolean finished = false;
private Cipher cipher;
private SecretKeySpec keySpec;
private byte[] iv;
public FileEncryptedGetRequest(short handle, FossilHRWatchAdapter adapter) {
this.handle = handle;
this.adapter = adapter;
@ -62,12 +64,42 @@ public abstract class FileEncryptedGetRequest extends FossilRequest {
.array();
}
private void initDecryption() {
try {
cipher = Cipher.getInstance("AES/CTR/NoPadding");
keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
iv = new byte[16];
byte[] phoneRandomNumber = adapter.getPhoneRandomNumber();
byte[] watchRandomNumber = adapter.getWatchRandomNumber();
System.arraycopy(phoneRandomNumber, 0, iv, 2, 6);
System.arraycopy(watchRandomNumber, 0, iv, 9, 7);
iv[7]++;
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
}
public FossilWatchAdapter getAdapter() {
return adapter;
}
private void incrementIV(){
ByteBuffer buffer = ByteBuffer.wrap(this.iv);
int number = buffer.getInt(12);
number += 0x1F;
buffer.position(12);
buffer.putInt(number);
this.iv = buffer.array();
}
@Override
public boolean isFinished(){
public boolean isFinished() {
return finished;
}
@ -75,73 +107,66 @@ public abstract class FileEncryptedGetRequest extends FossilRequest {
public void handleResponse(BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue();
byte first = value[0];
if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")){
if((first & 0x0F) == 1){
if (characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")) {
if ((first & 0x0F) == 1) {
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
this.initDecryption();
short handle = buffer.getShort(1);
int size = buffer.getInt(4);
byte status = buffer.get(3);
ResultCode code = ResultCode.fromCode(status);
if(!code.inidicatesSuccess()){
if (!code.inidicatesSuccess()) {
throw new RuntimeException("FileGet error: " + code + " (" + status + ")");
}
if(this.handle != handle){
if (this.handle != handle) {
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
log("file size: " + size);
fileBuffer = ByteBuffer.allocate(size);
}else if((first & 0x0F) == 8){
} else if ((first & 0x0F) == 8) {
this.finished = true;
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
short handle = buffer.getShort(1);
if(this.handle != handle){
if (this.handle != handle) {
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
CRC32 crc = new CRC32();
crc.update(this.fileData);
CRC32C c = new CRC32C();
c.update(this.fileData, 0, fileData.length);
int crcExpected = buffer.getInt(8);
if((int) crc.getValue() != crcExpected){
if ((int) crc.getValue() != crcExpected) {
throw new RuntimeException("crc: " + crc.getValue() + " expected: " + crcExpected);
}
this.handleFileData(this.fileData);
}
}else if(characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")){
SecretKeySpec keySpec = new SecretKeySpec(this.adapter.getSecretKey(), "AES");
} else if (characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")) {
try {
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
byte[] fileIV = new byte[16];
byte[] phoneRandomNumber = adapter.getPhoneRandomNumber();
byte[] watchRandomNumber = adapter.getWatchRandomNumber();
System.arraycopy(phoneRandomNumber, 0, fileIV, 2, 6);
System.arraycopy(watchRandomNumber, 0, fileIV, 9, 7);
fileIV[7]++;
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(fileIV));
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
byte[] result = cipher.doFinal(value);
incrementIV();
fileBuffer.put(result, 1, result.length - 1);
if((result[0] & 0x80) == 0x80){
if ((result[0] & 0x80) == 0x80) {
this.fileData = fileBuffer.array();
}
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
} catch (BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | InvalidKeyException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

View File

@ -1,7 +1,6 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file;
import android.bluetooth.BluetoothGattCharacteristic;
import android.widget.Toast;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -9,12 +8,9 @@ import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class FilePutRawRequest extends FossilRequest {
public enum UploadState {INITIALIZED, UPLOADING, CLOSING, UPLOADED}
@ -71,8 +67,10 @@ public class FilePutRawRequest extends FossilRequest {
this.prepareFilePackets(this.file);
for (byte[] packet : packets) {
for (int i = 0, packetCount = packets.size(); i < packetCount; i++) {
byte[] packet = packets.get(i);
transactionBuilder.write(uploadCharacteristic, packet);
onPacketWritten(transactionBuilder, i, packetCount);
}
transactionBuilder.queue(adapter.getDeviceSupport().getQueue());
@ -197,6 +195,11 @@ public class FilePutRawRequest extends FossilRequest {
}
public void onFilePut(boolean success) {
}
public void onPacketWritten(TransactionBuilder transactionBuilder, int packetNr, int packetCount) {
}
@Override

View File

@ -0,0 +1,32 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file;
import android.content.Context;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class FirmwareFilePutRequest extends FilePutRawRequest {
public FirmwareFilePutRequest(byte[] firmwareBytes, FossilHRWatchAdapter adapter) {
super((short) 0x00FF, firmwareBytes, adapter);
}
@Override
public void onPacketWritten(TransactionBuilder transactionBuilder, int packetNr, int packetCount) {
int progressPercent = (int) ((((float) packetNr) / packetCount) * 100);
transactionBuilder.add(new SetProgressAction(GBApplication.getContext().getString(R.string.updatefirmwareoperation_update_in_progress), true, progressPercent, GBApplication.getContext()));
}
@Override
public void onFilePut(boolean success) {
Context context = GBApplication.getContext();
if (success) {
GB.updateInstallNotification(context.getString(R.string.updatefirmwareoperation_update_complete), false, 100, context);
} else {
GB.updateInstallNotification(context.getString(R.string.updatefirmwareoperation_write_failed), false, 0, context);
}
}
}

View File

@ -17,6 +17,13 @@ public class AssetImage extends AssetFile {
this.indexZ = indexZ;
}
protected AssetImage(byte[] fileData, String fileName, int angle, int distance, int indexZ) {
super(fileName, fileData);
this.angle = angle;
this.distance = distance;
this.indexZ = indexZ;
}
@NonNull
@Override
public String toString() {

View File

@ -16,7 +16,13 @@ public class AssetImageFactory {
return new AssetImage(fileData, angle, distance, indexZ);
}
// method created for creating empty files, which turned out not to work anyway
private static AssetImage createAssetImage(byte[] fileData, String fileName, int angle, int distance, int indexZ){
return new AssetImage(fileData, fileName, angle, distance, indexZ);
}
public static AssetImage createAssetImage(Bitmap fileData, boolean RLEencode, int angle, int distance, int indexZ) throws IOException {
if(RLEencode == (distance == 0)) throw new RuntimeException("when RLEencoding distance must be 0, image must be at center of screen");
if(RLEencode){
int height = fileData.getHeight();
int width = fileData.getWidth();

View File

@ -17,26 +17,10 @@ public class CustomWidget extends Widget {
this.name = name;
}
public int getAngle() {
return angle;
}
public int getDistance() {
return distance;
}
public void setElements(ArrayList<CustomWidgetElement> elements) {
this.elements = elements;
}
public void setAngle(int angle) {
this.angle = angle;
}
public void setDistance(int distance) {
this.distance = distance;
}
public void setName(String name) {
this.name = name;
}

View File

@ -21,6 +21,22 @@ public class Widget implements Serializable {
this.fontColor = fontColor;
}
public int getAngle() {
return angle;
}
public int getDistance() {
return distance;
}
public void setAngle(int angle) {
this.angle = angle;
}
public void setDistance(int distance) {
this.distance = distance;
}
@NonNull
@Override
public String toString() {

View File

@ -4,9 +4,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FilePutRawRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.json.JsonPutRequest;
public class WidgetsPutRequest extends JsonPutRequest {

View File

@ -48,6 +48,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.hplus.EXRIZUK8Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.MakibesF68Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipLiteCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbips.AmazfitBipSCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.itag.ITagCoordinator;
@ -217,6 +218,7 @@ public class DeviceHelper {
result.add(new AmazfitCor2Coordinator());
result.add(new AmazfitGTRCoordinator());
result.add(new AmazfitGTSCoordinator());
result.add(new AmazfitBipSCoordinator());
result.add(new MiBand3Coordinator());
result.add(new MiBand4Coordinator());
result.add(new MiBand2HRXCoordinator());

View File

@ -51,10 +51,12 @@ import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2;
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import static nodomain.freeyourgadget.gadgetbridge.GBApplication.isRunningOreoOrLater;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_RECORDED_DATA_TYPES;
public class GB {
@ -112,6 +114,7 @@ public class GB {
builder.addAction(R.drawable.ic_notification_disconnected, context.getString(R.string.controlcenter_disconnect), disconnectPendingIntent);
if (GBApplication.isRunningLollipopOrLater() && DeviceHelper.getInstance().getCoordinator(device).supportsActivityDataFetching()) { //for some reason this fails on KK
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_FETCH_RECORDED_DATA);
deviceCommunicationServiceIntent.putExtra(EXTRA_RECORDED_DATA_TYPES, ActivityKind.TYPE_ACTIVITY);
PendingIntent fetchPendingIntent = PendingIntent.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT);
builder.addAction(R.drawable.ic_action_fetch_activity_data, context.getString(R.string.controlcenter_fetch_activity_data), fetchPendingIntent);
}

View File

@ -0,0 +1,342 @@
/* Copyright (C) 2020 Ted Stein
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.util;
import java.util.Optional;
import java.text.Normalizer;
import java.text.Normalizer.Form;
// Implements Revised Romanization of Korean as well as we can without understanding any grammar.
//
// https://en.wikipedia.org/wiki/Revised_Romanization_of_Korean
public class KoreanLanguageUtils {
// https://en.wikipedia.org/wiki/Hangul_Jamo_%28Unicode_block%29
private static final char JAMO_BLOCK_START = 0x1100;
private static final char JAMO_BLOCK_END = 0x11FF;
// https://en.wikipedia.org/wiki/Hangul_Syllables
private static final char SYLLABLES_BLOCK_START = 0xAC00;
private static final char SYLLABLES_BLOCK_END = 0xD7A3;
// https://en.wikipedia.org/wiki/Hangul_Compatibility_Jamo
private static final char COMPAT_JAMO_BLOCK_START = 0x3131;
private static final char COMPAT_JAMO_BLOCK_END = 0x318E;
// Returns whether a char is in the given block. Both bounds are inclusive.
private static boolean inRange(char c, char start, char end) {
return c >= start && c <= end;
}
// User input consisting of isolated jamo is usually mapped to the KS X 1001 compatibility
// block, but jamo resulting from decomposed syllables are mapped to the modern one. This
// function maps compat jamo to modern ones where possible and returns all other characters
// unmodified.
//
// https://en.wikipedia.org/wiki/Hangul_Compatibility_Jamo
// https://en.wikipedia.org/wiki/Hangul_Jamo_%28Unicode_block%29
private static char decompatJamo(char jamo) {
// KS X 1001 Hangul filler, not used in modern Unicode. A useful landmark in the
// compatibility jamo block.
// https://en.wikipedia.org/wiki/KS_X_1001#Hangul_Filler
final char HANGUL_FILLER = 0x3164;
// Don't do anything to characters outside the compatibility jamo block.
if (!inRange(jamo, COMPAT_JAMO_BLOCK_START, COMPAT_JAMO_BLOCK_END)) { return jamo; }
// Vowels are contiguous, in the same order, and unambiguous, so it's a simple offset.
if (jamo >= 0x314F && jamo < HANGUL_FILLER) {
return (char)(jamo - 0x1FEE);
}
// Consonants are organized differently. No clean way to do this.
//
// The compatibility jamo block doesn't distinguish between Choseong (leading) and Jongseong
// (final) positions, but the modern block does. We map to Choseong here.
switch (jamo) {
case 0x3131: return 0x1100; //
case 0x3132: return 0x1101; //
case 0x3134: return 0x1102; //
case 0x3137: return 0x1103; //
case 0x3138: return 0x1104; //
case 0x3139: return 0x1105; //
case 0x3141: return 0x1106; //
case 0x3142: return 0x1107; //
case 0x3143: return 0x1108; //
case 0x3145: return 0x1109; //
case 0x3146: return 0x110A; //
case 0x3147: return 0x110B; //
case 0x3148: return 0x110C; //
case 0x3149: return 0x110D; //
case 0x314A: return 0x110E; //
case 0x314B: return 0x110F; //
case 0x314C: return 0x1110; //
case 0x314D: return 0x1111; //
case 0x314E: return 0x1112; //
}
// The rest of the compatibility block consists of archaic compounds that are unlikely to be
// encountered in modern systems. Just leave them alone.
return jamo;
}
// Transliterates jamo one at a time. Returns its input if it isn't in the modern jamo block.
private static String transliterateSingleJamo(char jamo) {
jamo = decompatJamo(jamo);
switch (jamo) {
// Choseong (leading position consonants)
case 0x1100: return "g"; //
case 0x1101: return "kk"; //
case 0x1102: return "n"; //
case 0x1103: return "d"; //
case 0x1104: return "tt"; //
case 0x1105: return "r"; //
case 0x1106: return "m"; //
case 0x1107: return "b"; //
case 0x1108: return "pp"; //
case 0x1109: return "s"; //
case 0x110A: return "ss"; //
case 0x110B: return ""; //
case 0x110C: return "j"; //
case 0x110D: return "jj"; //
case 0x110E: return "ch"; //
case 0x110F: return "k"; //
case 0x1110: return "t"; //
case 0x1111: return "p"; //
case 0x1112: return "h"; //
// Jungseong (vowels)
case 0x1161: return "a"; //
case 0x1162: return "ae"; //
case 0x1163: return "ya"; //
case 0x1164: return "yae"; //
case 0x1165: return "eo"; //
case 0x1166: return "e"; //
case 0x1167: return "yeo"; //
case 0x1168: return "ye"; //
case 0x1169: return "o"; //
case 0x116A: return "wa"; //
case 0x116B: return "wae"; //
case 0x116C: return "oe"; //
case 0x116D: return "yo"; //
case 0x116E: return "u"; //
case 0x116F: return "wo"; //
case 0x1170: return "we"; //
case 0x1171: return "wi"; //
case 0x1172: return "yu"; //
case 0x1173: return "eu"; //
case 0x1174: return "ui"; //
case 0x1175: return "i"; //
// Jongseong (final position consonants)
case 0x11A8: return "k"; //
case 0x11A9: return "k"; //
case 0x11AB: return "n"; //
case 0x11AE: return "t"; //
case 0x11AF: return "l"; //
case 0x11B7: return "m"; //
case 0x11B8: return "p"; //
case 0x11BA: return "t"; //
case 0x11BB: return "t"; //
case 0x11BC: return "ng"; //
case 0x11BD: return "t"; //
case 0x11BE: return "t"; //
case 0x11BF: return "k"; //
case 0x11C0: return "t"; //
case 0x11C1: return "p"; //
case 0x11C2: return "t"; //
}
// Input was not jamo.
return String.valueOf(jamo);
}
// Some combinations of ending jamo in one syllable and initial jamo in the next are romanized
// irregularly. These exceptions are called "special provisions". In cases where multiple
// romanizations are permitted, we use the one that's least commonly used elsewhere.
//
// Returns no value if either character is not in the modern jamo block, or if there is no
// special provision for that pair of jamo.
public static Optional<String> transliterateSpecialProvisions(char previousEnding, char nextInitial) {
// Special provisions only apply if both characters are in the modern jamo block.
if (!inRange(previousEnding, JAMO_BLOCK_START, JAMO_BLOCK_END)) { return Optional.empty(); }
if (!inRange(nextInitial, JAMO_BLOCK_START, JAMO_BLOCK_END)) { return Optional.empty(); }
// Jongseong (final position) has a number of special provisions.
if (previousEnding == 0x11C2) { //
switch (nextInitial) {
case 0x110B: return Optional.of("h"); //
case 0x1100: return Optional.of("k"); //
case 0x1102: return Optional.of("nn"); //
case 0x1103: return Optional.of("t"); //
case 0x1105: return Optional.of("nn"); //
case 0x1106: return Optional.of("nm"); //
case 0x1107: return Optional.of("p"); //
case 0x1109: return Optional.of("hs"); //
case 0x110C: return Optional.of("ch"); //
case 0x1112: return Optional.of("t"); //
default: return Optional.empty();
}
}
// Otherwise, special provisions are denser when grouped by the second jamo.
switch (nextInitial) {
case 0x1100: //
switch (previousEnding) {
case 0x11AB: return Optional.of("n-g"); //
default: return Optional.empty();
}
case 0x1102: //
switch (previousEnding) {
case 0x11A8: return Optional.of("ngn"); //
case 0x11AE: //
case 0x11BA: //
case 0x11BD: //
case 0x11BE: //
case 0x11C0: //
return Optional.of("nn");
case 0x11AF: return Optional.of("ll"); //
case 0x11B8: return Optional.of("mn"); //
default: return Optional.empty();
}
case 0x1105: //
switch (previousEnding) {
case 0x11A8: //
case 0x11AB: //
case 0x11AF: //
return Optional.of("ll");
case 0x11AE: //
case 0x11BA: //
case 0x11BD: //
case 0x11BE: //
case 0x11C0: //
return Optional.of("nn");
case 0x11B7: //
case 0x11B8: //
return Optional.of("mn");
case 0x11BC: return Optional.of("ngn"); //
default: return Optional.empty();
}
case 0x1106: //
switch (previousEnding) {
case 0x11A8: return Optional.of("ngm"); //
case 0x11AE: //
case 0x11BA: //
case 0x11BD: //
case 0x11BE: //
case 0x11C0: //
return Optional.of("nm");
case 0x11B8: return Optional.of("mm"); //
default: return Optional.empty();
}
case 0x110B: //
switch (previousEnding) {
case 0x11A8: return Optional.of("g"); //
case 0x11AE: return Optional.of("d"); //
case 0x11AF: return Optional.of("r"); //
case 0x11B8: return Optional.of("b"); //
case 0x11BA: return Optional.of("s"); //
case 0x11BC: return Optional.of("ng-"); //
case 0x11BD: return Optional.of("j"); //
case 0x11BE: return Optional.of("ch"); //
default: return Optional.empty();
}
case 0x110F: //
switch (previousEnding) {
case 0x11A8: return Optional.of("k-k"); //
default: return Optional.empty();
}
case 0x1110: //
switch (previousEnding) {
case 0x11AE: //
case 0x11BA: //
case 0x11BD: //
case 0x11BE: //
case 0x11C0: //
return Optional.of("t-t");
default: return Optional.empty();
}
case 0x1111: //
switch (previousEnding) {
case 0x11B8: return Optional.of("p-p"); //
default: return Optional.empty();
}
default: return Optional.empty();
}
}
// Decompose a syllable into several jamo. Returns its input if that isn't possible.
public static char[] decompose(char syllable) {
String normalized = Normalizer.normalize(String.valueOf(syllable), Normalizer.Form.NFD);
return normalized.toCharArray();
}
// Transliterate any Hangul in the given string. Leaves any non-Hangul characters unmodified.
public static String transliterate(String txt) {
if (txt == null || txt.isEmpty()) {
return txt;
}
// Most of the bulk of these loops is for handling special provisions - situations where the
// last jamo of one syllable and the first of the next need to be romanized as a pair in an
// irregular way.
StringBuilder builder = new StringBuilder();
boolean nextInitialJamoConsumed = false;
char[] syllables = txt.toCharArray();
for (int i = 0; i < syllables.length; i++) {
char thisSyllable = syllables[i];
// If this isn't in any of the Hangul blocks we know about, emit it as-is.
if (!inRange(thisSyllable, JAMO_BLOCK_START, JAMO_BLOCK_END)
&& !inRange(thisSyllable, SYLLABLES_BLOCK_START, SYLLABLES_BLOCK_END)
&& !inRange(thisSyllable, COMPAT_JAMO_BLOCK_START, COMPAT_JAMO_BLOCK_END)) {
builder.append(thisSyllable);
continue;
}
char[] theseJamo = decompose(thisSyllable);
for (int j = 0; j < theseJamo.length; j++) {
char thisJamo = theseJamo[j];
// If we already transliterated the first jamo of this syllable as part of a special
// provision, skip it. Otherwise, handle it in the unconditional else branch.
if (j == 0 && nextInitialJamoConsumed) {
nextInitialJamoConsumed = false;
continue;
}
// If this is the last jamo of this syllable and not the last syllable of the
// string, check for special provisions. If the next char is whitespace or not
// Hangul, it's the responsibility of transliterateSpecialProvisions() to return no
// value.
if (j == theseJamo.length - 1 && i < syllables.length - 1) {
char nextSyllable = syllables[i + 1];
char nextJamo = decompose(nextSyllable)[0];
Optional<String> specialProvision = transliterateSpecialProvisions(thisJamo, nextJamo);
if (specialProvision.isPresent()) {
builder.append(specialProvision.get());
nextInitialJamoConsumed = true;
} else {
// No special provision applies. Transliterate in isolation.
builder.append(transliterateSingleJamo(thisJamo));
}
continue;
}
// Everything else is transliterated in isolation.
builder.append(transliterateSingleJamo(thisJamo));
}
}
return builder.toString();
}
}

View File

@ -77,12 +77,14 @@ public class LanguageUtils {
put('ق', "q"); put('ك', "k"); put('ل', "l"); put('م', "m"); put('ن', "n"); put('ه', "h");
put('و', "w"); put('ي', "y"); put('ى', "a"); put('ﺓ', "");
put('آ', "2"); put('ئ', "2"); put('إ', "2"); put('ؤ', "2"); put('أ', "2"); put('ء', "2");
put('٠', "0"); put('١', "1"); put('٢', "2"); put('٣', "3"); put('٤', "4"); put('٥', "5");
put('٦', "6"); put('٧', "7"); put('٨', "8"); put('٩', "9");
// Persian(Farsi)
put('پ', "p"); put('چ', "ch"); put('ژ', "zh"); put('ک', "k"); put('گ', "g"); put('ی', "y"); put('', " ");
put('؟', "?"); put('٪', "%"); put('؛', ";"); put('،', ","); put('۱', "1"); put('۲', "2"); put('۳', "3");
put('۴', "4"); put('۵', "5"); put('۶', "6"); put('۷', "7"); put('۸', "8"); put('۹', "9"); put('۰', "0");
put('»', "<"); put('«', ">"); put('ِ', "e"); put('َ', "a"); put('ُ', "o"); put('ّ', "");
put('»', "<"); put('«', ">"); put('ِ', "e"); put('َ', "a"); put('ُ', "o"); put('ّ', "");
// Polish
put('Ł', "L"); put('ł', "l");
@ -114,18 +116,21 @@ public class LanguageUtils {
return txt;
}
StringBuilder message = new StringBuilder();
StringBuilder messageBuilder = new StringBuilder();
// Simple, char-by-char transliteration.
char[] chars = txt.toCharArray();
for (char c : chars)
{
message.append(transliterate(c));
messageBuilder.append(transliterate(c));
}
String message = messageBuilder.toString();
String messageString = BengaliLanguageUtils.transliterate(message.toString());
// More complex transliteration for specific languages.
message = BengaliLanguageUtils.transliterate(message);
message = KoreanLanguageUtils.transliterate(message);
return flattenToAscii(messageString);
return flattenToAscii(message);
}
/**

View File

@ -96,4 +96,26 @@
android:layout_height="wrap_content"
android:text="add widget" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:orientation="horizontal">
<Button
android:id="@+id/qhybrid_unset_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="delete background"
android:layout_weight="1"/>
<Button
android:id="@+id/qhybrid_set_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="set background"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/qhybrid_image_edit_container"
android:layout_above="@id/qhybrid_image_edit_okay"
android:layout_alignParentTop="true">
<ImageView
android:id="@+id/qhybrid_image_edit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_dark"/>
<ImageView
android:id="@+id/qhybrid_image_edit_image_overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ok"
android:id="@+id/qhybrid_image_edit_okay"
android:layout_alignParentBottom="true"/>
</RelativeLayout>

View File

@ -845,4 +845,9 @@
<string name="pref_title_upper_button_function">Botó superior</string>
<string name="pref_title_middle_button_function">Botó mitger</string>
<string name="pref_title_lower_button_function">Botó inferior</string>
<string name="pref_title_relax_firmware_checks">Activeu-ho si voleu instal·lar microprogramari no destinat al vostre aparell (sota la vostra responsabilitat)</string>
<string name="pref_summary_relax_firmware_checks">Relaxa les comprovacions de microprogramari</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_vibration_strength">Intensitat de vibració</string>
<string name="pref_header_auto_fetch">Recollida automàtica</string>
</resources>

View File

@ -816,7 +816,7 @@
<string name="prefs_button_triple_press_action_selection_title">Akce události 3</string>
<string name="prefs_button_variable_actions">Detailní nastavení stisku tlačítka</string>
<string name="prefs_button_long_press_action_selection_title">Akce pro dlouhý stisk</string>
<string name="alarm_snooze">Později...</string>
<string name="alarm_snooze">Odložit</string>
<string name="error_no_location_access">Přístup k poloze musí být díky systému Android přístupů povolen a zapnut, aby bylo možno správně naskenovat zařízení</string>
<string name="devicetype_itag">iTag</string>
<string name="pref_title_allow_high_mtu">Povolit vyšší MTU</string>
@ -834,4 +834,21 @@
<string name="find_lost_device_you_found_it">Nalezeno!</string>
<string name="pref_title_force_white_color_scheme">Vynutit barevné schéma Černá na bílé</string>
<string name="pref_summary_force_white_color_scheme">Užitečné, pokud máte hodinky s tmavými ručičkami</string>
<string name="find_my_phone_notification">Najít telefon</string>
<string name="notification_channel_high_priority_name">Gadgetbridge oznámení s vysokou prioritou</string>
<string name="pref_title_custom_deviceicon">Zobrazit v oznámení ikonu připojeného zařízení</string>
<string name="pref_summary_custom_deviceicon">Zobrazit ikonu konkrétního připojeného zařízení v oznámení Androidu namísto ikony Gadgetbridge</string>
<string name="hr_appname_wellness">Wellness</string>
<string name="hr_appname_workout">Cvičení</string>
<string name="hr_appname_stopwatch">Stopky</string>
<string name="hr_appname_commute">Dojíždění</string>
<string name="pref_title_upper_button_function">Horní Tlačítko</string>
<string name="pref_title_middle_button_function">Prostřední Tlačítko</string>
<string name="pref_title_lower_button_function">Dolní Tlačítko</string>
<string name="pref_title_vibration_strength">Síla vibrací</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_relax_firmware_checks">Aktivujte tuto možnost, pokud chcete flashovat firmware, který není určen pro vaše zařízení (na vlastní nebezpečí)</string>
<string name="pref_summary_relax_firmware_checks">Uvolněte kontroly firmwaru</string>
<string name="pref_qhybrid_title_widget_draw_circles">Nakreslete kruhy widgetu</string>
<string name="pref_header_auto_fetch">Stahovat automaticky</string>
</resources>

View File

@ -54,7 +54,7 @@
<!--Strings related to Settings-->
<string name="title_activity_settings">Einstellungen</string>
<string name="pref_header_general">Allgemeine Einstellungen</string>
<string name="pref_title_general_autoconnectonbluetooth">Mit Gadgetbridge-Gerät verbinden, wenn Bluetooth eingeschaltet ist</string>
<string name="pref_title_general_autoconnectonbluetooth">Mit Gadgetbridge-Gerät verbinden, wenn Bluetooth eingeschaltet wird</string>
<string name="pref_title_general_autostartonboot">Automatisch starten</string>
<string name="pref_title_general_autoreconnect">Verbindung automatisch wiederherstellen</string>
<string name="pref_title_audio_player">Bevorzugter Audioplayer</string>
@ -78,7 +78,7 @@
<string name="pref_title_notifications_generic">Unterstützung allgemeine Benachrichtigung</string>
<string name="pref_title_whenscreenon">…auch wenn der Bildschirm an ist</string>
<string name="pref_title_notification_filter">Bitte nicht stören</string>
<string name="pref_summary_notification_filter">Unerwünschte Benachrichtigungen werden in diesem Modus gestoppt</string>
<string name="pref_summary_notification_filter">Unerwünschte Benachrichtigungen werden in diesem Modus unterdrückt</string>
<string name="pref_title_transliteration">Umwandlung</string>
<string name="pref_summary_transliteration">Aktiviere dies, falls dein Gerät keine Unterstützung für die Schriftart deiner Sprache hat</string>
<string name="always">Immer</string>
@ -131,7 +131,7 @@
<string name="pref_title_pebble_forceprotocol">Benachrichtigungsprotokoll erzwingen</string>
<string name="pref_summary_pebble_forceprotocol">Diese Option erzwingt das neuste Benachrichtigungsprotokoll abhängig von der Firmwareversion. NUR EINSCHALTEN, WENN DU WEISST, WAS DU TUST!</string>
<string name="pref_title_pebble_forceuntested">Ungetestete Features aktivieren</string>
<string name="pref_summary_pebble_forceuntested">Ungetestete Funktionen aktivieren. WEISST DU WAS DU TUST!</string>
<string name="pref_summary_pebble_forceuntested">Aktiviere ungetestete Funktionen. SEI DIR SICHER WAS DU DA TUST!</string>
<string name="pref_title_pebble_forcele">BLE immer bevorzugen</string>
<string name="pref_summary_pebble_forcele">Nutze die experimentelle LE-Unterstützung für alle Pebbles anstelle von BT-Classic. Dies erfordert zuerst eine Kopplung mit Nicht-LE und dann Pebble LE</string>
<string name="pref_title_pebble_mtu_limit">Pebble 2/LE GATT MTU Limit</string>
@ -145,7 +145,7 @@
<string name="pref_title_timeformat">Zeitformat</string>
<string name="pref_title_screentime">Bildschirm-An-Dauer</string>
<string name="prefs_title_all_day_heart_rate">Ganztägige Herzfrequenzmessung</string>
<string name="preferences_hplus_settings">HPlus/Makibes Einstellungen</string>
<string name="preferences_hplus_settings">HPlus/Makibes-Einstellungen</string>
<string name="not_connected">Nicht verbunden</string>
<string name="connecting">Verbindung wird hergestellt</string>
<string name="connected">Verbunden</string>
@ -192,7 +192,7 @@
<string name="pairing_already_bonded">Bereits an %1$s (%2$s) gebunden, verbinden…</string>
<string name="message_cannot_pair_no_mac">Keine MAC-Adresse erhalten, koppeln nicht möglich.</string>
<string name="preferences_category_device_specific_settings">Gerätespezifische Einstellungen</string>
<string name="preferences_miband_settings">Mi Band / Amazfit Einstellungen</string>
<string name="preferences_miband_settings">Mi Band- / Amazfit-Einstellungen</string>
<string name="male">Männlich</string>
<string name="female">Weiblich</string>
<string name="other">Andere</string>
@ -268,7 +268,7 @@
<string name="weeksleepchart_today_sleep_description">Schlaf heute, Ziel: %1$s</string>
<string name="weekstepschart_steps_a_week">Schritte pro Woche</string>
<string name="activity_sleepchart_activity_and_sleep">Aktivität</string>
<string name="updating_firmware">Firmware aktualisieren</string>
<string name="updating_firmware">Aktualisiere Firmware</string>
<string name="fwapp_install_device_not_ready">Datei kann nicht installiert werden, Gerät nicht bereit.</string>
<string name="installhandler_firmware_name">%1$s: %2$s %3$s</string>
<string name="miband_fwinstaller_compatible_version">Kompatible Version</string>
@ -352,7 +352,7 @@
<string name="charts_legend_heartrate">Herzfrequenz</string>
<string name="live_activity_heart_rate">Herzfrequenz</string>
<string name="pref_title_pebble_health_store_raw">Rohdaten in der Datenbank speichern</string>
<string name="pref_summary_pebble_health_store_raw">Speichert Daten \"wie sie sind\" und erhöht die Datenbanknutzung, um eine spätere Auswertung zu ermöglichen.</string>
<string name="pref_summary_pebble_health_store_raw">Speichert Daten „wie sie sind“ und erhöht die Datenbanknutzung, um eine spätere Auswertung zu ermöglichen.</string>
<string name="action_db_management">Datenbankverwaltung</string>
<string name="title_activity_db_management">Datenbankverwaltung</string>
<string name="activity_db_management_import_export_explanation">Die Datenbankoperationen verwenden den folgenden Pfad auf deinem Gerät.
@ -487,7 +487,7 @@
<string name="pref_title_auto_export_interval">Exportintervall</string>
<string name="pref_summary_auto_export_interval">Alle %d Stunden exportieren</string>
<string name="notif_export_failed_title">Datenbankexport fehlgeschlagen! Bitte überprüfe deine Einstellungen.</string>
<string name="mi2_prefs_button_press_broadcast_summary">Broadcast-Nachricht, die mit dem Ereignis gesendet wurde. Der Parameter \"button_id\" wird automatisch zu jeder Nachricht hinzugefügt.</string>
<string name="mi2_prefs_button_press_broadcast_summary">Broadcast-Nachricht, die mit dem Ereignis gesendet wurde. Der Parameter „button_id“ wird automatisch zu jeder Nachricht hinzugefügt.</string>
<string name="mi2_prefs_button_press_count_match_delay_summary">Verzögerung nach einer Tastenaktion (Zahl in button_id) oder 0 für sofort</string>
<string name="spanish">Spanisch</string>
<string name="on">Ein</string>
@ -541,7 +541,7 @@
<string name="whitelist_all_for_notifications">Whitelist für alle Benachrichtigungen</string>
<string name="pref_auto_fetch_summary">Abruf erfolgt beim Entsperren des Bildschirms. Funktioniert nur, wenn ein Sperrmechanismus eingestellt ist!</string>
<string name="watch9_pairing_tap_hint">Wenn deine Uhr vibriert, schüttel das Gerät oder drücke die Taste.</string>
<string name="preferences_qhybrid_settings">Q Hybrid Einstellungen</string>
<string name="preferences_qhybrid_settings">Q Hybrid-Einstellungen</string>
<string name="watch9_calibration_button">Kalibrieren</string>
<string name="title_activity_watch9_pairing">Watch 9 koppeln</string>
<string name="watch9_time_minutes">Minuten:</string>
@ -606,7 +606,7 @@
<string name="pref_invalid_frequency_message">Bitte eine Frequenz zwischen 87,5 und 108,0 eingeben</string>
<string name="language_and_region_prefs">Sprach- und Regionseinstellungen</string>
<string name="debugactivity_really_factoryreset_title">Wirklich auf Werkseinstellungen zurücksetzen\?</string>
<string name="debugactivity_really_factoryreset">Beim Zurücksetzen auf die Werkseinstellungen werden alle Daten vom angeschlossenen Gerät gelöscht (falls unterstützt). Xiaomi/Huami-Geräte ändern auch die Bluetooth-MAC-Adresse, so dass sie als neue Geräte bei Gadgetbridge erscheinen.</string>
<string name="debugactivity_really_factoryreset">Beim Zurücksetzen auf die Werkseinstellungen werden alle Daten vom angeschlossenen Gerät gelöscht (falls unterstützt). Xiaomi/Huami-Geräte wechseln dabei auch die Bluetooth-MAC-Adresse, so dass sie als neue Geräte bei Gadgetbridge erscheinen.</string>
<string name="pref_rtl_max_line_length_summary">Verlängert oder verkürzt die Zeilen, in die der Rechts-nach-Links Text getrennt wird</string>
<string name="notif_battery_low_extended">%1$s Akku schwach: %2$s</string>
<string name="lack_of_sleep">Schlafmangel: %1$s</string>
@ -641,7 +641,7 @@
<string name="activity_prefs_distance_meters">Tägliches Ziel: zurückgelegte Strecke in Meter</string>
<string name="activity_prefs_activetime_minutes">Tägliches Ziel: aktive Zeit in Minuten</string>
<!-- ZeTime Preferences -->
<string name="zetime_title_settings">ZeTime Einstellungen</string>
<string name="zetime_title_settings">ZeTime-Einstellungen</string>
<string name="zetime_title_screentime">Display-Aktivierungsdauer in Sekunden</string>
<string name="activity_prefs_alarm_max_heart_rate">Hohe Herzfrequenzschwelle</string>
<string name="activity_prefs_alarm_min_heart_rate">Niedrige Herzfrequenzschwelle</string>
@ -764,7 +764,7 @@
<item quantity="one">%d Std</item>
<item quantity="other">%d Std</item>
</plurals>
<string name="preferences_makibes_hr3_settings">Makibes HR3 Einstellungen</string>
<string name="preferences_makibes_hr3_settings">Makibes HR3-Einstellungen</string>
<string name="devicetype_makibes_hr3">Makibes HR3</string>
<string name="devicetype_amazfit_bip_lite">Amazfit Bip Lite</string>
<string name="prefs_find_phone">Telefon finden</string>
@ -792,7 +792,7 @@
<string name="pref_chart_heartrate_color_orange">Orange</string>
<string name="pref_title_chart_heartrate_color">Farbe der Herzfrequenz</string>
<string name="pref_title_chart_sleep_rolling_24_hour">Schlafbereich</string>
<string name="pref_chart_sleep_rolling_24_on">Letzten 24 Stunden</string>
<string name="pref_chart_sleep_rolling_24_on">Letzte 24 Stunden</string>
<string name="pref_chart_sleep_rolling_24_off">Mittag bis Mittag</string>
<string name="devicetype_amazfit_gts">Amazfit GTS</string>
<string name="fw_upgrade_notice_amazfitgts">Du bist dabei, die Firmware %s auf deine Amazfit GTS zu installieren.
@ -831,7 +831,7 @@
<string name="prefs_button_single_press_action_selection_title">Aktion bei einem einzigen Tastendruck</string>
<string name="prefs_button_double_press_action_selection_title">Aktion bei 2 Tastendrücken</string>
<string name="prefs_button_triple_press_action_selection_title">Aktion bei 3 Tastendrücken</string>
<string name="pref_title_allow_high_mtu">Hohe MTU erlauben</string>
<string name="pref_title_allow_high_mtu">Größere MTU erlauben</string>
<string name="pref_summary_sync_calendar">Aktiviert Kalendererinnerungen, auch wenn die Verbindung getrennt ist</string>
<string name="pref_title_sync_caldendar">Kalenderereignisse synchronisieren</string>
<string name="hr_widget_heart_rate">Herzfrequenz</string>
@ -855,4 +855,11 @@
<string name="pref_title_upper_button_function">Obere Taste</string>
<string name="pref_title_middle_button_function">Mittlere Taste</string>
<string name="pref_title_lower_button_function">Untere Taste</string>
<string name="pref_title_vibration_strength">Vibrationsstärke</string>
<string name="hr_appname_commute">Pendeln</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_summary_relax_firmware_checks">Firmwareüberprüfung deaktivieren</string>
<string name="pref_title_relax_firmware_checks">Aktiviere das flashen von Firmware, die nicht für dieses Gerät bestimmt ist (auf eigenes Risiko)</string>
<string name="pref_qhybrid_title_widget_draw_circles">Widget-Kreise zeichnen</string>
<string name="pref_header_auto_fetch">Automatischer Abruf</string>
</resources>

View File

@ -0,0 +1,853 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pref_title_chart_heartrate_color">Heart rate colour</string>
<string name="pref_title_force_white_color_scheme">Force black on white colour scheme</string>
<string name="controlcenter_change_led_color">Change LED colour</string>
<string name="notif_battery_low_percent">%1$s battery left: %2$s%%</string>
<plurals name="widget_alarm_target_hours">
<item quantity="one">%d hour</item>
<item quantity="other">%d hours</item>
</plurals>
<string name="pbwinstallhandler_app_item">%1$s (%2$s)</string>
<string name="installhandler_firmware_name">%1$s: %2$s %3$s</string>
<string name="notif_battery_low_extended">%1$s battery low: %2$s</string>
<string name="notif_battery_low">%1$s battery low</string>
<string name="device_with_rssi">%1$s (%2$s)</string>
<string name="appversion_by_creator">%1$s by %2$s</string>
<string name="pref_qhybrid_title_widget_draw_circles">Draw widget circles</string>
<string name="pref_header_auto_fetch">Auto fetch</string>
<string name="pref_title_relax_firmware_checks">Enable this if you want to flash a firmware not intended for you device (at your own risk)</string>
<string name="pref_summary_relax_firmware_checks">Relax firmware checks</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_vibration_strength">Vibration strength</string>
<string name="pref_title_lower_button_function">Lower Button</string>
<string name="pref_title_middle_button_function">Middle Button</string>
<string name="pref_title_upper_button_function">Upper Button</string>
<string name="hr_appname_commute">Commute</string>
<string name="hr_appname_stopwatch">Stopwatch</string>
<string name="hr_appname_workout">Workout</string>
<string name="hr_appname_wellness">Wellness</string>
<string name="pref_summary_custom_deviceicon">Show a device specific Android notification icon instead the Gadgetbridge icon when connected</string>
<string name="pref_title_custom_deviceicon">Show device specific notification icon</string>
<string name="notification_channel_high_priority_name">Gadgetbridge notifications high priority</string>
<string name="find_my_phone_notification">Find my phone</string>
<string name="pref_summary_force_white_color_scheme">Useful if you your watch has dark hands</string>
<string name="find_lost_device_you_found_it">Found it!</string>
<string name="hr_widget_nothing">Nothing</string>
<string name="hr_widget_weather">Weather</string>
<string name="hr_widget_battery">Battery</string>
<string name="hr_widget_calories">Calories</string>
<string name="hr_widget_active_minutes">Active minutes</string>
<string name="hr_widget_date">Date</string>
<string name="hr_widget_steps">Steps</string>
<string name="hr_widget_heart_rate">Heart rate</string>
<string name="pref_title_sync_caldendar">Sync calendar events</string>
<string name="pref_summary_sync_calendar">Enables calendar alerts, even when disconnected</string>
<string name="pref_summary_allow_high_mtu">Increases transfer speed, but might not work on some Android devices.</string>
<string name="pref_title_allow_high_mtu">Allow high MTU</string>
<string name="devicetype_itag">iTag</string>
<string name="error_no_location_access">Location access must be granted and enabled for scanning to work properly</string>
<string name="alarm_snooze">Snooze</string>
<string name="prefs_button_long_press_action_selection_title">Long press button action</string>
<string name="prefs_button_variable_actions">Detailed button press settings</string>
<string name="prefs_button_triple_press_action_selection_title">Event 3 action</string>
<string name="prefs_button_double_press_action_selection_title">Event 2 action</string>
<string name="prefs_button_single_press_action_selection_title">Event 1 action</string>
<string name="devicetype_y5">Y5</string>
<string name="devicetype_banglejs">Bangle.js</string>
<string name="pref_summary_disable_new_ble_scanning">Check this option if your device cannot be found during discovery</string>
<string name="pref_disable_new_ble_scanning">Disable new BLE scanning</string>
<string name="qhybrid_offset_time_by">offset time by</string>
<string name="qhybrid_changes_delay_prompt">change might take some seconds…</string>
<string name="qhybrid_offset_timezone">offset timezone by</string>
<string name="qhybrid_buttons_overwrite_error">Error overwriting buttons</string>
<string name="qhybrid_buttons_overwrite_success">Buttons overwritten</string>
<string name="qhybrid_prompt_million_steps">Please set the step count to a million to activate that.</string>
<string name="qhybrid_use_activity_hand_as_notification_counter">use activity hand as notification counter</string>
<string name="qhybrid_overwrite_buttons">overwrite buttons</string>
<string name="qhybrid_second_timezone_offset_relative_to_utc">second timezone offset relative to UTC</string>
<string name="qhybrid_time_shift">time shift</string>
<string name="qhybrid_goal_in_steps">Goal in steps</string>
<string name="qhybrid_vibration_strength">vibration strength:</string>
<string name="watch_not_connected">Watch not connected</string>
<string name="preferences_qhybrid_settings">Q Hybrid Settings</string>
<string name="devicetype_qhybrid">Fossil Q Hybrid</string>
<string name="fw_upgrade_notice_amazfitgts">You are about to install the %s firmware on your Amazfit GTS.
\n
\nPlease make sure to install the .fw file, then the .res file, and finally the .gps file. Your watch will reboot after installing the .fw file.
\n
\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.
\n
\nPROCEED AT YOUR OWN RISK!</string>
<string name="devicetype_amazfit_gts">Amazfit GTS</string>
<string name="pref_chart_sleep_rolling_24_off">Noon to noon</string>
<string name="pref_chart_sleep_rolling_24_on">Past 24 hours</string>
<string name="pref_title_chart_sleep_rolling_24_hour">Sleep range</string>
<string name="pref_chart_heartrate_color_orange">Orange</string>
<string name="pref_chart_heartrate_color_red">Red</string>
<string name="fw_upgrade_notice_amazfitgtr">You are about to install the %s firmware on your Amazfit GTR.
\n
\nPlease make sure to install the .fw file, then the .res file, and finally the .gps file. Your watch will reboot after installing the .fw file.
\n
\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.
\n
\nPROCEED AT YOUR OWN RISK!</string>
<string name="devicetype_amazfit_gtr">Amazfit GTR</string>
<string name="fw_upgrade_notice_amazfitbip_lite">You are about to install the %s firmware on your Amazfit Bip Lite.
\n
\nPlease make sure to install the .fw file, and after that the .res file. Your watch 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="discovery_need_to_enter_authkey">This device needs a secret auth key, long press on the device to enter it. Read the wiki.</string>
<string name="maximum_duration">Duration</string>
<string name="prefs_find_phone_duration">Ring duration in seconds</string>
<string name="prefs_find_phone_summary">Use your band to play your phone\'s ringtone.</string>
<string name="prefs_enable_find_phone">Turn on \\\'Find phone\\\'</string>
<string name="prefs_find_phone">Find phone</string>
<string name="devicetype_amazfit_bip_lite">Amazfit Bip Lite</string>
<string name="prefs_wearside">Wearing left or right\?</string>
<string name="devicetype_makibes_hr3">Makibes HR3</string>
<string name="preferences_makibes_hr3_settings">Makibes HR3 settings</string>
<string name="activity_error_no_app_for_gpx">To view activity trace, install app which can handle GPX files.</string>
<string name="pref_display_add_device_fab_off">Visible only if no device is added</string>
<string name="pref_display_add_device_fab_on">Always visible</string>
<string name="pref_display_add_device_fab">Connect new device button</string>
<string name="widget_1_hour">1 hour</string>
<string name="widget_20_minutes">20 minutes</string>
<string name="widget_10_minutes">10 minutes</string>
<string name="widget_5_minutes">5 minutes</string>
<string name="widget_set_alarm_after">Set alarm after:</string>
<string name="widget_listing_label">Status and Alarms</string>
<string name="widget_sleep_label">Sleep: %1$s</string>
<string name="widget_steps_label">Steps: %1$02d</string>
<string name="appwidget_sleep_alarm_widget_label">Sleep Alarm</string>
<string name="activity_db_management_empty_db_warning">Warning! By pushing this button you will wipe your database and start from scratch.</string>
<string name="activity_db_management_exportimport_label">Export and Import</string>
<string name="activity_db_management_empty_DB">Empty Database</string>
<string name="activity_DB_empty_button">Empty DB</string>
<string name="activity_DB_delete_legacy_button">Delete old DB</string>
<string name="activity_DB_test_export_message">Exporting database…</string>
<string name="activity_DB_test_export_button">Run AutoExport Now</string>
<string name="activity_DB_import_button">Import DB</string>
<string name="activity_DB_ExportButton">Export DB</string>
<string name="activity_db_management_autoexport_label">AutoExport</string>
<string name="activity_db_management_autoexport_explanation">Database autoexport location has been set to:</string>
<string name="pref_summary_use_custom_font">Enable this if your device has a custom font firmware for emoji support</string>
<string name="pref_title_use_custom_font">Use custom font</string>
<string name="pref_title_expose_hr">3rd party realtime HR access</string>
<string name="pref_summary_expose_hr">Allows other apps to access HR data in realtime while Gadgetbridge is connected</string>
<string name="menuitem_nfc">NFC</string>
<string name="devicetype_mijia_lywsd02">Mijia Smart Clock</string>
<string name="weeksleepchart_sleep_a_month">Sleep per month</string>
<string name="weekstepschart_steps_a_month">Steps per month</string>
<string name="pref_charts_range_off">Charts range is set to a Week</string>
<string name="pref_charts_range_on">Charts range is set to a Month</string>
<string name="pref_title_charts_range">Charts Range</string>
<string name="pref_title_charts_average">Show averages in the charts</string>
<string name="pref_header_charts">Charts Settings</string>
<string name="average">Average: %1$s</string>
<string name="prefs_hr_alarm_high">High limit</string>
<string name="prefs_hr_alarm_low">Low limit</string>
<string name="prefs_hr_alarm_activity">Heart rate alarm during sports activity</string>
<string name="fw_upgrade_notice_miband4">You are about to install the %s firmware on your Mi Band 4.
\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="devicetype_miband4">Mi Band 4</string>
<string name="devicetype_amazfit_cor2">Amazfit Cor 2</string>
<string name="portuguese">Portuguese</string>
<string name="vietnamese">Vietnamese</string>
<string name="thai">Thai</string>
<string name="indonesian">Indonesian</string>
<string name="arabic">Arabic</string>
<string name="ukrainian">Ukrainian</string>
<string name="turkish">Turkish</string>
<string name="dutch">Dutch</string>
<string name="fw_upgrade_notice_amazfitcor2">You are about to install the %s firmware on your Amazfit Cor 2.
\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!
\n
\nCOMPLETELY UNTESTED, PROBABLY YOU NEED TO FLASH A BEATS_W FIRMWARE IF YOUR DEVICE NAME IS \"Amazfit Band 2\"</string>
<string name="devicetype_bfh16">BFH-16</string>
<string name="pref_summary_authkey">Change the auth key to a common key on all your Android devices from which you would like to connect from. The previous default key for all devices is 0123456789@ABCDE</string>
<string name="pref_title_authkey">Auth Key</string>
<string name="title_activity_device_specific_settings">Device specific settings</string>
<string name="pref_title_support_voip_calls">Enable VoIP app calls</string>
<string name="devicetype_miscale2">Mi Scale 2</string>
<string name="activity_prefs_activetime_minutes">Daily target: active time in minutes</string>
<string name="activity_prefs_calories_burnt">Daily target: calories burnt</string>
<string name="interval_forty_five_minutes">every 45 minutes</string>
<string name="interval_fifteen_minutes">every 15 minutes</string>
<string name="pref_screen_notification_profile_anti_loss">Anti-loss warning</string>
<string name="pref_screen_notification_profile_low_power">Low power warning</string>
<string name="pref_screen_notification_profile_inactivity">Inactivity notification</string>
<string name="pref_screen_notification_profile_calendar">Calendar notification</string>
<string name="pref_screen_notification_profile_missed_call">Missed call notification</string>
<string name="zetime_signaling_vibrate_beep_once">Vibrate and beep once</string>
<string name="zetime_signaling_beep_twice">Beep twice</string>
<string name="zetime_signaling_beep_once">Beep once</string>
<string name="zetime_signaling_vibrate_twice">Vibrate twice</string>
<string name="zetime_signaling_vibrate_once">Vibrate once</string>
<string name="zetime_signaling_vibrate_beep">Continuous vibration and beeping</string>
<string name="zetime_signaling_beep">Continuous beeping</string>
<string name="zetime_signaling_vibrate">Continuous vibration</string>
<string name="zetime_signaling_none">Silent</string>
<string name="zetime_title_alarm_signaling">Set type of signaling for the alarm</string>
<string name="zetime_prefs_inactivity_su">Sunday</string>
<string name="zetime_prefs_inactivity_sa">Saturday</string>
<string name="zetime_prefs_inactivity_fr">Friday</string>
<string name="zetime_prefs_inactivity_th">Thursday</string>
<string name="zetime_prefs_inactivity_we">Wednesday</string>
<string name="zetime_prefs_inactivity_tu">Tuesday</string>
<string name="zetime_prefs_inactivity_mo">Monday</string>
<string name="zetime_prefs_inactivity_repetitions">Repetitions</string>
<string name="zetime_date_format_3">MM/DD/YY</string>
<string name="zetime_date_format_2">DD/MM/YY</string>
<string name="zetime_date_format_1">YY/MM/DD</string>
<string name="zetime_date_format">Date format</string>
<string name="zetime_calories_type_all">Active and inactive burnt calories</string>
<string name="zetime_calories_type_active">Only active burnt calories</string>
<string name="zetime_calories_type">Calories type</string>
<string name="zetime_handmove_display_summary">Rotate your wrist to activate or deactivate the display.</string>
<string name="zetime_handmove_display">Hand movement</string>
<string name="zetime_activity_tracking_summary">Switching the activity tracking on, will count your steps and so on.</string>
<string name="zetime_activity_tracking">Activity tracking</string>
<string name="zetime_analog_mode_handsandsteps">Hands and steps</string>
<string name="zetime_analog_mode_hands">Only hands</string>
<string name="zetime_analog_mode">Analog mode</string>
<string name="activity_prefs_alarm_min_heart_rate">Min heart rate</string>
<string name="activity_prefs_alarm_max_heart_rate">Max heart rate</string>
<string name="zetime_heart_rate_alarm_enable">Enable the heart rate alarm</string>
<string name="zetime_title_heart_rate_alarm_summary">The watch will warn you when your heart rate exceeds the limits.</string>
<string name="zetime_title_heart_rate_alarm">Heart rate alarm</string>
<string name="zetime_title_screentime">Screen on duration in seconds</string>
<string name="zetime_title_heartrate">Heart rate settings</string>
<string name="zetime_title_settings">ZeTime settings</string>
<string name="prefs_disconnect_notification">Disconnect notification</string>
<string name="activity_type_exercise">Exercise</string>
<string name="appwidget_not_connected">Not connected, alarm not set.</string>
<string name="save_configuration">Save Configuration</string>
<string name="mode_configuration">Mode Configuration</string>
<string name="filter_mode">Filter Mode</string>
<string name="toast_notification_filter_words_empty_hint">Please enter at least one word</string>
<string name="filter_submode_all">All of the words</string>
<string name="filter_submode_at_least_one">At least one of the words</string>
<string name="filter_mode_blacklist">Block when words are contained</string>
<string name="filter_mode_whitelist">Show when words are contained</string>
<string name="filter_mode_none">Do not filter</string>
<string name="toast_notification_filter_saved_successfully">Notification filter saved</string>
<string name="edittext_notification_filter_words_hint">Enter desired words, new line for each</string>
<string name="toast_app_must_not_be_blacklisted">App must not be blacklisted to be configured</string>
<string name="preferences_rtl_settings">Right To Left Support</string>
<string name="pref_summary_contextual_arabic">Enable this to support contextual Arabic</string>
<string name="pref_title_contextual_arabic">Contextual Arabic</string>
<string name="pref_rtl_max_line_length_summary">Lengthens or shortens the lines Right-To-Left text is separated into</string>
<string name="pref_rtl_max_line_length">Right-To-Left Max Line Length</string>
<string name="pref_summary_rtl">Enable this if your device can not show right-to-left languages</string>
<string name="pref_title_rtl">Right-To-Left</string>
<string name="activity_prefs_chart_min_heart_rate">Min heart rate</string>
<string name="activity_prefs_chart_max_heart_rate">Max heart rate</string>
<string name="activity_prefs_charts">Chart settings</string>
<string name="pref_invalid_frequency_message">Please enter a frequency between 87.5 and 108.0</string>
<string name="pref_invalid_frequency_title">Invalid frequency</string>
<string name="preferences_fm_frequency">FM Frequency</string>
<string name="devicetype_roidmi3">Roidmi 3</string>
<string name="devicetype_roidmi">Roidmi</string>
<string name="controlcenter_change_fm_frequency">Change FM Frequency</string>
<string name="warning">Warning!</string>
<string name="share_log_warning">Please keep in mind Gadgetbridge logs files that may contain lots of personal info, including but not limited to health data, unique identifiers (such as a device\'s MAC address), music preferences, etc. Consider editing the file and removing this info before sending the file to a public issue report.</string>
<string name="share_log">Share log</string>
<string name="ok">OK</string>
<string name="mi3_night_mode_sunset">At sunset</string>
<string name="mi3_prefs_night_mode_summary">Lower band screen brightness automatically at night</string>
<string name="mi3_prefs_night_mode">Night mode</string>
<string name="minutes_30">30 minutes</string>
<string name="minutes_10">10 minutes</string>
<string name="minutes_5">5 minutes</string>
<string name="minutes_1">1 minute</string>
<string name="seconds_30">30 seconds</string>
<string name="seconds_20">20 seconds</string>
<string name="seconds_10">10 seconds</string>
<string name="seconds_5">5 seconds</string>
<string name="no_limit">No limit</string>
<string name="pref_title_notifications_timeout">Minimum time between notifications</string>
<string name="norwegian_bokmal">Norwegian Bokmål</string>
<string name="you_did_not_sleep">You did not sleep</string>
<string name="you_slept">You slept from %1$s to %2$s</string>
<string name="japanese">Japanese</string>
<string name="korean">Korean</string>
<string name="polish">Polish</string>
<string name="french">French</string>
<string name="italian">Italian</string>
<string name="german">German</string>
<string name="mi3_prefs_band_screen_unlock_summary">Swipe up to unlock the band\'s screen</string>
<string name="mi3_prefs_band_screen_unlock">Band screen unlock</string>
<string name="title_activity_watch9_calibration">Watch 9 calibration</string>
<string name="title_activity_watch9_pairing">Watch 9 pairing</string>
<string name="watch9_calibration_button">Calibrate</string>
<string name="watch9_calibration_hint">Set the time your device is showing to you right now.</string>
<string name="watch9_time_seconds">Seconds:</string>
<string name="watch9_time_hours">Hours:</string>
<string name="watch9_time_minutes">Minutes:</string>
<string name="devicetype_watch9">Watch 9</string>
<string name="watch9_pairing_tap_hint">When your watch vibrates, shake the device or press its button.</string>
<string name="controlcenter_calibrate_device">Calibrate Device</string>
<string name="menuitem_music">Music</string>
<string name="menuitem_more">More</string>
<string name="menuitem_notifications">Notifications</string>
<string name="devicetype_id115">ID115</string>
<string name="vertical">Vertical</string>
<string name="horizontal">Horizontal</string>
<string name="prefs_screen_orientation">Screen orientation</string>
<string name="russian">Russian</string>
<string name="devicetype_mykronoz_zetime">MyKronoz ZeTime</string>
<string name="pref_auto_fetch_limit_fetches_summary">Fetches every %d minutes</string>
<string name="pref_auto_fetch_limit_fetches">Minimum time between fetches</string>
<string name="pref_auto_fetch_summary">Fetch happens upon screen unlock. Only works if a lock mechanism is set!</string>
<string name="pref_auto_fetch">Auto fetch activity data</string>
<string name="whitelist_all_for_notifications">Whitelist all for notifications</string>
<string name="blacklist_all_for_notifications">Blacklist all for notifications</string>
<string name="devicetype_miband3">Mi Band 3</string>
<string name="activity_prefs_distance_meters">Daily target: distance in metres</string>
<string name="mi2_prefs_button_press_broadcast_summary">Broadcast message sent with the event. Parameter button_id is added automatically to each message.</string>
<string name="preferences_led_color">LED colour</string>
<string name="fw_upgrade_notice_miband3">You are about to install the %s firmware on your Mi Band 3.
\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="devicetype_q8">Q8</string>
<string name="menuitem_shortcut_weather">Weather (Shortcut)</string>
<string name="menuitem_shortcut_alipay">Alipay (Shortcut)</string>
<string name="pref_summary_pebble_gatt_clientonly">This is for Pebble 2 only and experimental, try this if you have connectivity problems</string>
<string name="pref_title_pebble_gatt_clientonly">GATT client only</string>
<string name="menuitem_alipay">Alipay</string>
<string name="menuitem_settings">Settings</string>
<string name="menuitem_compass">Compass</string>
<string name="menuitem_timer">Timer</string>
<string name="menuitem_alarm">Alarm</string>
<string name="menuitem_weather">Weather</string>
<string name="menuitem_activity">Activity</string>
<string name="menuitem_status">Status</string>
<string name="reset_index">Reset fetch date</string>
<string name="share">Share</string>
<string name="select_all">Select all</string>
<string name="pref_title_audio_player">Preferred Audioplayer</string>
<string name="pref_title_general_autoreconnect">Reconnect automatically</string>
<string name="activity_type_treadmill">Treadmill</string>
<string name="activity_type_biking">Biking</string>
<string name="activity_summaries">Activities</string>
<string name="activity_type_unknown">Unknown activity</string>
<string name="activity_type_swimming">Swimming</string>
<string name="activity_type_walking">Walking</string>
<string name="activity_type_running">Running</string>
<string name="activity_type_not_worn">Device not worn</string>
<string name="activity_type_deep_sleep">Deep sleep</string>
<string name="activity_type_light_sleep">Light sleep</string>
<string name="activity_type_activity">Activity</string>
<string name="activity_type_not_measured">Not measured</string>
<string name="controlcenter_start_activity_tracks">Your activity tracks</string>
<string name="on">On</string>
<string name="devicetype_xwatch">XWatch</string>
<string name="notification_channel_name">Gadgetbridge notifications</string>
<string name="spanish">Spanish</string>
<string name="choose_auto_export_location">Choose export location</string>
<string name="notif_export_failed_title">Export database failed! Please check your settings.</string>
<string name="pref_summary_auto_export_interval">Export every %d hour</string>
<string name="pref_title_auto_export_interval">Export interval</string>
<string name="pref_title_auto_export_location">Export location</string>
<string name="pref_title_auto_export_enabled">Auto export enabled</string>
<string name="pref_header_auto_export">Auto export</string>
<string name="pref_title_weather">Weather</string>
<string name="devicetype_teclast_h30">Teclast H30</string>
<string name="devicetype_no1_f1">No.1 F1</string>
<string name="devicetype_exrizu_k8">Exrizu K8</string>
<string name="devicetype_makibes_f68">Makibes F68</string>
<string name="devicetype_hplus">HPlus</string>
<string name="devicetype_liveview">LiveView</string>
<string name="devicetype_vibratissimo">Vibratissimo</string>
<string name="devicetype_amazfit_cor">Amazfit Cor</string>
<string name="devicetype_amazfit_bip">Amazfit Bip</string>
<string name="devicetype_miband2">Mi Band 2</string>
<string name="devicetype_miband">Mi Band</string>
<string name="devicetype_pebble">Pebble</string>
<string name="devicetype_test">Test Device</string>
<string name="devicetype_unknown">Unknown Device</string>
<string name="kind_watchface">Watchface</string>
<string name="kind_resources">Resources</string>
<string name="kind_gps_cep">GPS Error Correction</string>
<string name="kind_gps_almanac">GPS Almanac</string>
<string name="kind_gps">GPS Firmware</string>
<string name="kind_font">Font</string>
<string name="kind_invalid">Invalid data</string>
<string name="kind_firmware">Firmware</string>
<string name="pref_title_weather_location">Weather location (CM/LOS)</string>
<string name="interval_one_hour">once an hour</string>
<string name="interval_thirty_minutes">every 30 minutes</string>
<string name="interval_ten_minutes">every 10 minutes</string>
<string name="interval_five_minutes">every 5 minutes</string>
<string name="interval_one_minute">once a minute</string>
<string name="prefs_title_heartrate_measurement_interval">Whole day HR measurement</string>
<string name="english">English</string>
<string name="traditional_chinese">Traditional Chinese</string>
<string name="simplified_chinese">Simplified Chinese</string>
<string name="automatic">Automatic</string>
<string name="pref_title_charts_swipe">Enable left/right swipe in the charts activity</string>
<string name="fw_upgrade_notice_amazfitcor">You are about to install the %s firmware on your Amazfit Cor.
\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="controlcenter_connect">Connect…</string>
<string name="activity_web_view">Web View Activity</string>
<string name="pref_summary_pebble_enable_bgjs">When enabled, allows watchfaces to show weather, battery info etc.</string>
<string name="pref_title_pebble_enable_bgjs">Enable background JS</string>
<string name="_pebble_watch_reply">Reply</string>
<string name="_pebble_watch_mute">Mute</string>
<string name="_pebble_watch_open_on_phone">Open on Android device</string>
<string name="mi2_prefs_button_press_count_max_delay_summary">Maximum delay between button presses in milliseconds</string>
<string name="mi2_prefs_button_press_count_max_delay">Maximum delay between presses</string>
<string name="mi2_prefs_button_action_vibrate_summary">Enable band vibration on button action triggered</string>
<string name="mi2_prefs_button_action_vibrate">Enable band vibration</string>
<string name="mi2_prefs_button_action_summary">Enable action on specified number of button presses</string>
<string name="mi2_prefs_button_action">Enable button action</string>
<string name="mi2_prefs_button_press_broadcast">Broadcast message to send</string>
<string name="mi2_prefs_button_press_count_summary">Number of button presses to trigger an Event 1. Subsequent same amount of presses create Event 2 and so on.</string>
<string name="mi2_prefs_button_press_count">Button press count</string>
<string name="mi2_prefs_button_actions_summary">Specify button press actions</string>
<string name="mi2_prefs_button_actions">Button actions</string>
<string name="fw_upgrade_notice_amazfitbip">You are about to install the %s firmware on your Amazfit Bip.
\n
\nPlease make sure to install the .fw file, then the .res file, and finally the .gps file. Your watch will reboot after installing the .fw file.
\n
\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.
\n
\nPROCEED AT YOUR OWN RISK!</string>
<string name="discovery_dont_pair">Don\'t Pair</string>
<string name="discovery_yes_pair">Pair</string>
<string name="discovery_pair_question">Select Pair to pair your devices. If this fails, try again without pairing.</string>
<string name="discovery_pair_title">Pair with %1$s\?</string>
<string name="discovery_successfully_bonded">Bound to %1$s.</string>
<string name="discovery_enable_bluetooth">Enable Bluetooth to discover devices.</string>
<string name="discovery_trying_to_connect_to">Trying to connect to: %1$s</string>
<string name="discovery_bonding_failed_immediately">Bonding with %1$s failed immediately.</string>
<string name="discovery_attempting_to_pair">Attempting to pair with %1$s</string>
<string name="mi2_dnd_scheduled">Scheduled (time interval)</string>
<string name="mi2_dnd_automatic">Automatic (sleep detection)</string>
<string name="mi2_dnd_off">Off</string>
<string name="off">Off</string>
<string name="mi2_enable_text_notifications_summary">Needs firmware &gt;= 1.0.1.28 and Mili_pro.ft* installed.</string>
<string name="mi2_enable_text_notifications">Text notifications</string>
<string name="mi2_fw_installhandler_fw53_hint">You need to install version %1$s before installing this firmware!</string>
<string name="miband2_prefs_timeformat">Mi2: Time format</string>
<string name="find_device_you_found_it">You found it!</string>
<string name="StringUtils_sender">(%1$s)</string>
<string name="pref_screen_notification_profile_alarm_clock">Alarm clock</string>
<string name="timeformat_am_pm">AM/PM</string>
<string name="timeformat_24h">24H</string>
<string name="unit_imperial">Imperial</string>
<string name="unit_metric">Metric</string>
<string name="pref_summary_setup_bt_pairing">Deactivate this if you have trouble connecting</string>
<string name="pref_title_setup_bt_pairing">Enable Bluetooth pairing</string>
<string name="weather_notification_label">Make sure that this skin is enabled in the Weather Notification app to get weather information on your Pebble.
\n
\nNo configuration is needed here.
\n
\nYou can enable the system weather app of your Pebble from the app management.
\n
\nSupported watchfaces will show the weather automatically.</string>
<string name="pebble_pairing_hint">A pairing dialog will pop up on your Android device. If not, look in the notification drawer and accept the pairing request. Also accept it on your Pebble afterwards.</string>
<string name="title_activity_pebble_pairing">Pebble pairing</string>
<string name="title_activity_vibration">Vibration</string>
<string name="Delete">Delete</string>
<string name="Cancel">Cancel</string>
<string name="dbmanagementactivity_overwrite">Overwrite</string>
<string name="dbmanagementactivity_old_activity_db_deletion_failed">Old Activity database deletion failed.</string>
<string name="dbmanagementactivity_old_activity_db_successfully_deleted">Old activity data deleted.</string>
<string name="dbmanagementactivity_delete_old_activitydb_confirmation">Really delete the old activity database\? Activity data that was not imported will be lost.</string>
<string name="dbmanagementactivity_delete_old_activity_db">Delete old Activity Database\?</string>
<string name="dbmanagementactivity_db_deletion_failed">Database deletion failed.</string>
<string name="dbmanagementactivity_database_successfully_deleted">Data deleted.</string>
<string name="dbmanagementactivity_really_delete_entire_db">Really delete the entire database\? All your activity data and information about your devices will be lost.</string>
<string name="dbmanagementactivity_delete_activity_data_title">Delete Activity Data\?</string>
<string name="dbmanagementactivity_error_importing_shared">Error importing preference: %1$s</string>
<string name="dbmanagementactivity_error_importing_db">Error importing DB: %1$s</string>
<string name="dbmanagementactivity_import_successful">Imported.</string>
<string name="dbmanagementactivity_overwrite_database_confirmation">Really overwrite the current database\? All your current activity data (if any) will be lost.</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="pref_title_pebble_health_store_raw">Store raw record in the database</string>
<string name="live_activity_heart_rate">Heart rate</string>
<string name="charts_legend_heartrate">Heart rate</string>
<string name="updatefirmwareoperation_firmware_not_sent">Firmware not sent</string>
<string name="updatefirmwareoperation_update_in_progress">Flashing firmware</string>
<string name="DEVINFO_HR_VER">"HR: "</string>
<string name="error_creating_directory_for_logfiles">Error creating directory for log files: %1$s</string>
<string name="device_fw">Firmware version: %1$s</string>
<string name="device_hw">Hardware revision: %1$s</string>
<string name="activity_prefs_sleep_duration">Preferred sleep duration in hours</string>
<string name="add_widget">Add widget</string>
<string name="appwidget_text">Zzz</string>
<string name="authentication_required">Authentication required</string>
<string name="authenticating">Authenticating</string>
<string name="activity_prefs_weight_kg">Weight in kg</string>
<string name="activity_prefs_height_cm">Height in cm</string>
<string name="activity_prefs_gender">Gender</string>
<string name="activity_prefs_year_birth">Year of birth</string>
<string name="activity_prefs_about_you">About you</string>
<string name="waiting_for_reconnect">Waiting for reconnect</string>
<string name="FetchActivityOperation_about_to_transfer_since">About to transfer data since %1$s</string>
<string name="mi2_prefs_do_not_disturb_end">End time</string>
<string name="mi2_prefs_do_not_disturb_start">Start time</string>
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Disable inactivity warnings for a time interval</string>
<string name="mi2_prefs_inactivity_warnings_threshold">Inactivity threshold (in minutes)</string>
<string name="mi2_prefs_inactivity_warnings_summary">The band will vibrate when you have been inactive for a while</string>
<string name="mi2_prefs_inactivity_warnings">Inactivity warnings</string>
<string name="mi2_prefs_do_not_disturb_summary">The band won\'t receive notifications while active</string>
<string name="mi2_prefs_do_not_disturb">Do Not Disturb</string>
<string name="mi2_prefs_rotate_wrist_to_switch_info">Rotate wrist to switch info</string>
<string name="mi2_prefs_activate_display_on_lift">Activate display upon lift</string>
<string name="mi2_prefs_display_items_summary">Choose the items displayed on the band screen</string>
<string name="mi2_prefs_display_items">Display items</string>
<string name="mi2_prefs_goal_notification_summary">The band will vibrate when the daily steps goal is reached</string>
<string name="mi2_prefs_goal_notification">Goal notification</string>
<string name="dateformat_date_time">Time &amp; date</string>
<string name="dateformat_time">Time</string>
<string name="miband2_prefs_dateformat">Date format</string>
<string name="miband_prefs_device_time_offset_hours">Device time offset in hours (for detecting sleep of shift workers)</string>
<string name="miband_prefs_hr_sleep_detection">Use heart rate sensor to improve sleep detection</string>
<string name="miband_prefs_reserve_alarm_calendar">Alarms to reserve for upcoming events</string>
<string name="fwinstaller_firmware_not_compatible_to_device">This firmware is not compatible with the device</string>
<string name="miband_fwinstaller_incompatible_version">Incompatible firmware</string>
<string name="pref_title_keep_data_on_device">Keep activity data on device</string>
<string name="user_feedback_all_alarms_disabled">All alarms disabled</string>
<string name="device_not_connected">Not connected.</string>
<string name="abstract_chart_fragment_kind_not_worn">Not worn</string>
<string name="abstract_chart_fragment_kind_deep_sleep">Deep sleep</string>
<string name="abstract_chart_fragment_kind_light_sleep">Light sleep</string>
<string name="abstract_chart_fragment_kind_activity">Activity</string>
<string name="live_activity_start_your_activity">Start your activity</string>
<string name="live_activity_steps_per_minute_history">Steps per minute history</string>
<string name="live_activity_total_steps">Total steps</string>
<string name="live_activity_current_steps_per_minute">Current steps/min</string>
<string name="live_activity_steps_history">Steps history</string>
<string name="pref_summary_low_latency_fw_update">This might help on devices where firmware flashing fails.</string>
<string name="pref_title_low_latency_fw_update">Use low-latency mode for firmware flashing</string>
<string name="pref_summary_keep_data_on_device">Will keep activity data on the Mi Band even after synchronization. Useful if GB is used together with other apps.</string>
<string name="pref_summary_dont_ack_transfers">If the activity data are not acked to the band, they will not be cleared. Useful if GB is used together with other apps.</string>
<string name="pref_title_dont_ack_transfer">Do not ACK activity data transfer</string>
<string name="weeksteps_today_steps_description">Steps today, target: %1$s</string>
<string name="liveactivity_live_activity">Live activity</string>
<string name="battery">Battery</string>
<string name="heart_rate">Heart rate</string>
<string name="clock">Clock</string>
<string name="distance">Distance</string>
<string name="calories">Calories</string>
<string name="chart_steps">Steps</string>
<string name="updatefirmwareoperation_write_failed">Firmware flashing failed</string>
<string name="updatefirmwareoperation_update_complete_rebooting">Firmware installation complete, rebooting device…</string>
<string name="updatefirmwareoperation_update_complete">Firmware installation complete</string>
<string name="title_activity_notification_filter">Notification Filter</string>
<string name="appwidget_setting_alarm">Setting alarm for %1$02d:%2$02d</string>
<string name="devicetype_casiogb6900">Casio GB-6900</string>
<string name="debugactivity_really_factoryreset">Doing a factory reset will delete all data from the connected device (if supported). Xiaomi/Huami devices also change Bluetooth MAC address, so they appear as a new devices to Gadgetbridge.</string>
<string name="debugactivity_really_factoryreset_title">Really factory reset\?</string>
<string name="live_activity_max_heart_rate">Current / Max heart rate: %1$d / %2$d</string>
<string name="no_data">No data</string>
<string name="overstep">Overstep: %1$d</string>
<string name="lack_of_step">Lack of steps: %1$d</string>
<string name="overslept">Overslept: %1$s</string>
<string name="lack_of_sleep">Lack of sleep: %1$s</string>
<string name="language_and_region_prefs">Language and region settings</string>
<string name="updatefirmwareoperation_metadata_updateproblem">Problem with the firmware metadata transfer</string>
<string name="updatefirmwareoperation_updateproblem_do_not_reboot">Problem with the firmware transfer. DO NOT REBOOT your Mi Band!</string>
<string name="pbwinstallhandler_incorrect_hw_revision">Hardware revision mismatch!</string>
<string name="pbwinstallhandler_correct_hw_revision">Correct hardware revision</string>
<string name="pbw_installhandler_pebble_firmware">Pebble Firmware %1$s</string>
<string name="fwappinstaller_connection_state">Connection to device: %1$s</string>
<string name="miband_fwinstaller_untested_version">Untested version!</string>
<string name="miband_fwinstaller_compatible_version">Compatible version</string>
<string name="fwapp_install_device_not_ready">File cannot be installed, device not ready.</string>
<string name="updating_firmware">Flashing firmware…</string>
<string name="activity_sleepchart_activity_and_sleep">Activity</string>
<string name="weekstepschart_steps_a_week">Steps per week</string>
<string name="weeksleepchart_today_sleep_description">Sleep today, target: %1$s</string>
<string name="weeksleepchart_sleep_a_week">Sleep per week</string>
<string name="sleepchart_your_sleep">Sleep</string>
<string name="notif_battery_low_bigtext_number_of_charges">Number of charges: %s</string>
<string name="notif_battery_low_bigtext_last_charge_time">Last charge: %s
\n</string>
<string name="notif_battery_low_title">Gadget battery Low!</string>
<string name="installer_activity_wait_while_determining_status">Please wait while determining the installation status…</string>
<string name="pbw_install_handler_hw_revision_mismatch">Unable to install the given firmware: It doesn\'t match your Pebble\'s hardware revision.</string>
<string name="pbw_install_handler_unable_to_install">Unable to install the given file: %1$s</string>
<string name="installer_activity_unable_to_find_handler">Unable to find a handler to install this file.</string>
<string name="cannot_connect">Cannot connect: %1$s</string>
<string name="controlcenter_start_activitymonitor">Your activity (ALPHA)</string>
<string name="dbaccess_error_executing">Error executing \'%1$s\'</string>
<string name="miband_prefs_fitness_goal">Daily step target</string>
<string name="user_feedback_miband_activity_data_transfer">About to transfer %1$s of data starting from %2$s</string>
<string name="chart_no_data_synchronize">No data. Synchronize device\?</string>
<string name="user_feedback_miband_set_alarms_ok">Alarms sent to device.</string>
<string name="user_feedback_miband_set_alarms_failed">There was an error setting the alarms, please try again.</string>
<string name="alarm_smart_wakeup">Smart wakeup</string>
<string name="alarm_sat_short">Sat</string>
<string name="alarm_fri_short">Fri</string>
<string name="alarm_thu_short">Thu</string>
<string name="alarm_wed_short">Wed</string>
<string name="alarm_tue_short">Tue</string>
<string name="alarm_mon_short">Mon</string>
<string name="alarm_sun_short">Sun</string>
<string name="title_activity_alarm_details">Alarm details</string>
<string name="controlcenter_start_configure_alarms">Configure alarms</string>
<string name="title_activity_set_alarm">Configure alarms</string>
<string name="title_activity_charts">Activity and Sleep</string>
<string name="control_center_cancel_to_stop_vibration">Cancel to stop vibration.</string>
<string name="control_center_find_lost_device">Find lost device</string>
<string name="stats_y_axis_label">Steps per minute</string>
<string name="stats_x_axis_label">Total minutes</string>
<string name="stats_title">Speed zones</string>
<string name="pref_screen_notification_profile_generic_social">Social network</string>
<string name="pref_screen_notification_profile_generic_navigation">Navigation</string>
<string name="pref_screen_notification_profile_generic_chat">Chat</string>
<string name="pref_screen_notification_profile_incoming_call">Incoming call notification</string>
<string name="pref_screen_notification_profile_email">E-mail notification</string>
<string name="pref_screen_notification_profile_generic">Generic notification</string>
<string name="pref_header_vibration_settings">Vibration settings</string>
<string name="pref_screen_notification_profile_sms">SMS notification</string>
<string name="vibration_try">Try</string>
<string name="miband_prefs_vibration">Vibration</string>
<string name="vibration_profile_alarm_clock">Alarm clock</string>
<string name="vibration_profile_ring">Ring</string>
<string name="vibration_profile_waterdrop">Waterdrop</string>
<string name="vibration_profile_long">Long</string>
<string name="vibration_profile_medium">Medium</string>
<string name="vibration_profile_short">Short</string>
<string name="vibration_profile_staccato">Staccato</string>
<string name="pref_screen_vibration_profile">Vibration profile</string>
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
<string name="busy_task_fetch_activity_data">Fetching activity data</string>
<string name="initializing">Initializing</string>
<string name="pref_write_logfiles">Write log files</string>
<string name="title_activity_sleepmonitor">Sleep monitor</string>
<string name="pref_header_vibration_count">Vibration count</string>
<string name="miband_prefs_alias">Name/Alias</string>
<string name="candidate_item_device_image">Device image</string>
<string name="discovery_note">Note:</string>
<string name="discovery_connected_devices_hint">Make your device discoverable. Currently connected devices will likely not be discovered. Activate location (e.g. GPS) on Android 6+. Disable Privacy Guard for Gadgetbridge, because it may crash and reboot your phone. If no device is found after a few minutes, try again after rebooting your mobile device.</string>
<string name="appinstaller_install">Install</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="miband_pairing_using_dummy_userdata">No valid user data given, using dummy user data for now.</string>
<string name="right">Right</string>
<string name="left">Left</string>
<string name="other">Other</string>
<string name="female">Female</string>
<string name="male">Male</string>
<string name="preferences_miband_settings">Mi Band / Amazfit settings</string>
<string name="preferences_category_device_specific_settings">Device specific settings</string>
<string name="message_cannot_pair_no_mac">No MAC address passed, cannot pair.</string>
<string name="pairing_already_bonded">Already bonded with %1$s (%2$s), connecting…</string>
<string name="pairing_in_progress">Bonding in progress: %1$s (%2$s)</string>
<string name="pairing_unable_to_pair_with">Unable to pair with %1$s (%2$s)</string>
<string name="pairing_creating_bond_with">Creating bond with %1$s (%2$s)</string>
<string name="pairing">Pairing with %s…</string>
<string name="title_activity_mi_band_pairing">Pair your Mi Band</string>
<string name="android_pairing_hint">Use the Android Bluetooth pairing dialog to pair the device.</string>
<string name="title_activity_android_pairing">Pair device</string>
<string name="action_discover">Connect new device</string>
<string name="discovery_start_scanning">Start discovery</string>
<string name="discovery_stop_scanning">Stop scanning</string>
<string name="title_activity_discovery">Device discovery</string>
<string name="initialized">initialized</string>
<string name="n_a">N/A</string>
<string name="app_install_info">You are about to install the following app:
\n
\n
\n%1$s Version %2$s by %3$s
\n</string>
<string name="firmware_install_warning">YOU ARE TRYING TO INSTALL A FIRMWARE, PROCEED AT YOUR OWN RISK.
\n
\n
\n This firmware is for HW Revision: %s</string>
<string name="installation_successful">Installed</string>
<string name="installation_failed_">Installation failed</string>
<string name="installing_binary_d_d">Installing binary %1$d/%2$d</string>
<string name="gadgetbridge_running">Gadgetbridge running</string>
<string name="cannot_connect_bt_address_invalid_">Cannot connect. Bluetooth address invalid\?</string>
<string name="tap_a_device_to_connect">Tap a device to connect</string>
<string name="tap_connected_device_for_vibration">Tap connected device for vibration</string>
<string name="tap_connected_device_for_activity">Tap connected device for activity</string>
<string name="tap_connected_device_for_app_mananger">Tap connected device for App manager</string>
<string name="bluetooth_is_disabled_">Bluetooth is disabled.</string>
<string name="bluetooth_is_not_supported_">Bluetooth is not supported.</string>
<string name="this_is_a_test_notification_from_gadgetbridge">This is a test notification from Gadgetbridge</string>
<string name="test_notification">Test notification</string>
<string name="test">Test</string>
<string name="_unknown_">(unknown)</string>
<string name="unknown_state">Unknown state</string>
<string name="connected">Connected</string>
<string name="connecting">Connecting</string>
<string name="not_connected">Not connected</string>
<string name="preferences_hplus_settings">HPlus/Makibes settings</string>
<string name="prefs_title_all_day_heart_rate">All day heart rate measurement</string>
<string name="pref_title_screentime">Screen on duration</string>
<string name="pref_title_timeformat">Time format</string>
<string name="pref_title_unit_system">Units</string>
<string name="pref_title_pebble_reconnect_attempts">Reconnection attempts</string>
<string name="pref_summary_pebble_always_ack_pebblekit">Will cause messages that are sent to external 3rd party apps to be acknowledged always and immediately</string>
<string name="pref_title_pebble_always_ack_pebblekit">Prematurely ACK PebbleKit</string>
<string name="pref_summary_pebble_enable_applogs">Will cause logs from watch apps to be logged by Gadgetbridge (requires reconnect)</string>
<string name="pref_title_pebble_enable_applogs">Enable watch app logging</string>
<string name="pref_summary_pebble_mtu_limit">If your Pebble 2/Pebble LE does not work as expected, try this setting to limit the MTU (valid range 20512)</string>
<string name="pref_title_pebble_mtu_limit">Pebble 2/LE GATT MTU limit</string>
<string name="pref_summary_pebble_forcele">Use experimental Pebble LE support for all Pebbles, instead of BT classic. This requires pairing to non LE first, and then Pebble LE</string>
<string name="pref_title_pebble_forcele">Always prefer BLE</string>
<string name="pref_summary_pebble_forceuntested">Enable untested features. KNOW WHAT YOU ARE DOING!</string>
<string name="pref_title_pebble_forceuntested">Enable untested features</string>
<string name="pref_summary_pebble_forceprotocol">This option forces using the latest notification protocol depending on the firmware version. KNOW WHAT YOU ARE DOING!</string>
<string name="pref_title_pebble_forceprotocol">Force notification protocol</string>
<string name="toast_aqurired_networklocation">location acquired</string>
<string name="toast_enable_networklocationprovider">Please enable network location</string>
<string name="pref_summary_location_keep_uptodate">Try to get the current location at runtime, use the stored location as fallback</string>
<string name="pref_title_location_keep_uptodate">Keep location updated</string>
<string name="pref_title_location_longitude">Longitude</string>
<string name="pref_title_location_latitude">Latitude</string>
<string name="pref_title_location_aquire">Acquire location</string>
<string name="pref_header_location">Location</string>
<string name="pref_pebble_privacy_mode_complete">Show only the notification icon</string>
<string name="pref_pebble_privacy_mode_content">Shift the notification text off-screen</string>
<string name="pref_pebble_privacy_mode_off">Normal notifications</string>
<string name="pref_title_pebble_privacy_mode">Privacy mode</string>
<string name="pref_summary_autoremove_notifications">Notifications are automatically removed from the Pebble when dismissed from the Android device</string>
<string name="pref_title_autoremove_notifications">Autoremove dismissed notifications</string>
<string name="pref_summary_enable_calendar_sync">Send calendar events to the timeline</string>
<string name="pref_title_enable_calendar_sync">Sync calendar</string>
<string name="pref_summary_sunrise_sunset">Send sunrise and sunset times based on the location to the Pebble timeline</string>
<string name="pref_title_sunrise_sunset">Sunrise and sunset</string>
<string name="pref_header_pebble_timeline">Pebble timeline</string>
<string name="pref_summary_enable_pebblekit">Enable experimental support for Android apps using PebbleKit</string>
<string name="pref_title_enable_pebblekit">Allow 3rd party Android App access</string>
<string name="pref_summary_enable_outgoing_call">Disabling this will also stop the Pebble 2/LE to vibrate on outgoing calls</string>
<string name="pref_title_enable_outgoing_call">Support outgoing calls</string>
<string name="pref_title_pebble_sync_morpheuz">Sync Morpheuz</string>
<string name="pref_title_pebble_sync_misfit">Sync Misfit</string>
<string name="pref_title_pebble_sync_health">Sync Pebble Health</string>
<string name="pref_title_pebble_activitytracker">Preferred activity tracker</string>
<string name="pref_header_activitytrackers">Activity trackers</string>
<string name="pref_title_pebble_settings">Pebble settings</string>
<string name="pref_title_development_miaddr">Mi Band address</string>
<string name="pref_header_development">Developer options</string>
<string name="pref_title_canned_messages_set">Update on Pebble</string>
<string name="pref_title_canned_messages_dismisscall">Call Dismissal</string>
<string name="pref_title_canned_reply_suffix">Common suffix</string>
<string name="pref_title_canned_replies">Replies</string>
<string name="pref_header_cannned_messages">Canned messages</string>
<string name="pref_blacklist_calendars">Blacklist Calendars</string>
<string name="pref_blacklist">Blacklist Apps</string>
<string name="pref_call_privacy_mode_complete">Hide name and number</string>
<string name="pref_call_privacy_mode_number">Hide number but display name</string>
<string name="pref_call_privacy_mode_name">Hide name but display number</string>
<string name="pref_call_privacy_mode_off">Display name and number</string>
<string name="pref_title_call_privacy_mode">Call privacy mode</string>
<string name="pref_header_privacy">Privacy</string>
<string name="never">Never</string>
<string name="when_screen_off">When screen is off</string>
<string name="always">Always</string>
<string name="pref_summary_transliteration">Enable this if your device has no support for your language\'s font</string>
<string name="pref_title_transliteration">Transliteration</string>
<string name="pref_summary_notification_filter">Unwanted notifications are stopped in this mode</string>
<string name="pref_title_notification_filter">Do Not Disturb</string>
<string name="pref_title_whenscreenon">…also when screen is on</string>
<string name="pref_title_notifications_generic">Generic notification support</string>
<string name="pref_summary_notifications_pebblemsg">Support for apps that send notifications to the Pebble via PebbleKit.</string>
<string name="pref_title_notifications_pebblemsg">Pebble Messages</string>
<string name="pref_title_notifications_sms">SMS</string>
<string name="pref_title_notifications_call">Phone Calls</string>
<string name="pref_title_notifications_repetitions">Repetitions</string>
<string name="pref_header_notifications">Notifications</string>
<string name="pref_summary_minimize_priority_on">The icon in the status bar and the notification in the lockscreen are hidden</string>
<string name="pref_summary_minimize_priority_off">The icon in the status bar and the notification in the lockscreen are shown</string>
<string name="pref_title_minimize_priority">Hide the Gadgetbridge notification</string>
<string name="pref_title_language">Language</string>
<string name="pref_theme_dark">Dark</string>
<string name="pref_theme_light">Light</string>
<string name="pref_title_theme">Theme</string>
<string name="pref_summary_datetime_syctimeonconnect">Sync time to Gadgetbridge device when connecting, and when time or time zone changes on Android device</string>
<string name="pref_title_datetime_syctimeonconnect">Sync time</string>
<string name="pref_header_datetime">Date and Time</string>
<string name="pref_default">Default</string>
<string name="pref_title_general_autostartonboot">Start automatically</string>
<string name="pref_title_general_autoconnectonbluetooth">Connect to Gadgetbridge device when Bluetooth is turned on</string>
<string name="pref_header_general">General settings</string>
<string name="title_activity_settings">Settings</string>
<string name="miband_firmware_suggest_whitelist">If you still want to proceed and things continue to work properly afterwards, please tell the Gadgetbridge developers to whitelist the %s firmware version.</string>
<string name="miband_firmware_unknown_warning">This firmware is untested and may not be compatible with Gadgetbridge.
\n
\nYou are DISCOURAGED from flashing it!</string>
<string name="miband_firmware_known">This firmware has been tested and is known to be compatible with Gadgetbridge.</string>
<string name="dbmanagementactivity_import_data_title">Import Data\?</string>
<string name="dbmanagementactivity_error_exporting_shared">Error exporting preference: %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">Error exporting DB: %1$s</string>
<string name="dbmanagementactivity_exported_to">Exported to: %1$s</string>
<string name="dbmanagementactivvity_cannot_access_export_path">Cannot access export path. Please contact the developers.</string>
<string name="activity_db_management_merge_old_title">Legacy database delete</string>
<string name="activity_db_management_import_export_explanation">The database operations use the following path on your device.
\nThis path is accessible to other Android apps and your computer.
\nExpect to find your exported database (or place the database you want to import) there:</string>
<string name="title_activity_db_management">Database management</string>
<string name="action_db_management">Database management</string>
<string name="fw_multi_upgrade_notice">You are about to install the %1$s and %2$s firmware, instead of the ones currently on your Mi Band.</string>
<string name="fw_upgrade_notice">You are about to install the %s.</string>
<string name="title_activity_fw_app_insaller">FW/App installer</string>
<string name="title_activity_calblacklist">Blacklisted Calendars</string>
<string name="title_activity_appblacklist">Notification blacklist</string>
<string name="app_move_to_top">Move to top</string>
<string name="app_configure">Configure</string>
<string name="appmanager_weather_install_provider">Install the Weather Notification app</string>
<string name="appmanager_weather_deactivate">Deactivate System Weather app</string>
<string name="appmanager_weather_activate">Activate System Weather app</string>
<string name="appmanager_hrm_deactivate">Deactivate HRM</string>
<string name="appmanager_hrm_activate">Activate HRM</string>
<string name="appmanager_health_deactivate">Deactivate</string>
<string name="appmanager_health_activate">Activate</string>
<string name="appmanager_app_openinstore">Search in Pebble appstore</string>
<string name="appmananger_app_reinstall">Reinstall</string>
<string name="appmananger_app_delete_cache">Delete and remove from cache</string>
<string name="appmananger_app_delete">Delete</string>
<string name="appmanager_installed_watchfaces">Installed watchfaces</string>
<string name="appmanager_installed_watchapps">Installed apps</string>
<string name="appmanager_cached_watchapps_watchfaces">Apps in cache</string>
<string name="title_activity_appmanager">App Manager</string>
<string name="title_activity_debug">Debug</string>
<string name="controlcenter_snackbar_requested_screenshot">Taking a screenshot of the device</string>
<string name="controlcenter_snackbar_connecting">Connecting…</string>
<string name="controlcenter_snackbar_disconnecting">Disconnecting</string>
<string name="controlcenter_snackbar_need_longpress">Long press the card to disconnect</string>
<string name="controlcenter_navigation_drawer_close">Close navigation drawer</string>
<string name="controlcenter_navigation_drawer_open">Open navigation drawer</string>
<string name="controlcenter_delete_device_dialogmessage">This will delete the device and all associated data!</string>
<string name="controlcenter_delete_device_name">Delete %1$s</string>
<string name="controlcenter_delete_device">Delete Device</string>
<string name="controlcenter_disconnect">Disconnect</string>
<string name="controlcenter_take_screenshot">Take Screenshot</string>
<string name="controlcenter_find_device">Find lost device</string>
<string name="controlcenter_fetch_activity_data">Synchronize</string>
<string name="action_donate">Donate</string>
<string name="action_quit">Quit</string>
<string name="action_debug">Debug</string>
<string name="action_settings">Settings</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="app_name">Gadgetbridge</string>
</resources>

View File

@ -829,4 +829,19 @@
<string name="devicetype_banglejs">Bangle.js</string>
<string name="devicetype_y5">Y5</string>
<string name="devicetype_itag">iTag</string>
<string name="pref_title_lower_button_function">Botón inferior</string>
<string name="pref_title_middle_button_function">Botón central</string>
<string name="pref_title_upper_button_function">Botón superior</string>
<string name="hr_appname_commute">Conmutar</string>
<string name="hr_appname_stopwatch">Cronógrafa</string>
<string name="hr_appname_workout">Rutina de ejercicio</string>
<string name="hr_appname_wellness">Bienestar</string>
<string name="pref_summary_force_white_color_scheme">Útil si tu reloj tiene manecillas oscuras</string>
<string name="find_my_phone_notification">Encuentra mi teléfono</string>
<string name="pref_title_vibration_strength">Resistencia a la vibración</string>
<string name="pref_title_relax_firmware_checks">Habilite esto si desea actualizar un firmware no destinado a su dispositivo (bajo su propio riesgo)</string>
<string name="pref_summary_relax_firmware_checks">Relaje las comprobaciones de firmware</string>
<string name="pref_title_allow_high_mtu">Permitir MTU alta</string>
<string name="pref_summary_custom_deviceicon">Mostrar un icono de notificación de Android específico del dispositivo en lugar del icono de Gadgetbridge cuando esté conectado</string>
<string name="pref_title_custom_deviceicon">Mostrar icono de notificación específica del dispositivo</string>
</resources>

View File

@ -0,0 +1,853 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="discovery_pair_title">Appairer avec %1$s\?</string>
<string name="dbmanagementactivity_delete_old_activitydb_confirmation">Voulez-vous vraiment détruire entièrement la base de données\? Toutes vos données non importées seront perdues.</string>
<string name="dbmanagementactivity_delete_old_activity_db">Voulez-vous détruire les anciennes activités de la base de données\?</string>
<string name="dbmanagementactivity_really_delete_entire_db">Voulez-vous vraiment détruire entièrement la base de données\? Toutes vos données d\'activité et vos informations issues de vos appareils seront perdues.</string>
<string name="dbmanagementactivity_delete_activity_data_title">Détruire les anciennes données\?</string>
<string name="dbmanagementactivity_overwrite_database_confirmation">Voulez-vous vraiment effacer la base de données actuelle\? Toutes vos données (si vous en avez) seront perdues.</string>
<string name="dbmanagementactivity_import_data_title">Importer des données\?</string>
<string name="chart_no_data_synchronize">Aucune donnée. Synchroniser l\'appareil\?</string>
<string name="prefs_wearside">Port main gauche ou droite\?</string>
<string name="cannot_connect_bt_address_invalid_">Connexion impossible. Ladresse Bluetooth est-elle valide\?</string>
<string name="debugactivity_really_factoryreset_title">Vraiment retourner aux paramètres d\'usine\?</string>
<string name="mi2_fw_installhandler_fw53_hint">Vous devez installer la version %1$s avant d\'installer ce micrologiciel!</string>
<string name="find_lost_device_you_found_it">Trouvé!</string>
<string name="find_device_you_found_it">Vous l\'avez trouvé!</string>
<string name="updatefirmwareoperation_updateproblem_do_not_reboot">Problème avec le transfert du micrologiciel. Ne redémarrez pas votre Mi Band!</string>
<string name="pbwinstallhandler_incorrect_hw_revision">Version du matériel incorrecte!</string>
<string name="miband_fwinstaller_untested_version">Version non testée!</string>
<string name="notif_export_failed_title">L\'exportation de la base de données a échoué! Veuillez vérifier vos paramètres.</string>
<string name="pref_auto_fetch_summary">Récupération au déverrouillage de l\'écran. Fonctionne uniquement si un mécanisme de verrouillage est configuré!</string>
<string name="pref_summary_pebble_forceuntested">Activer les fonctionnalités non-testées. À VOS PROPRES RISQUES ET PÉRILS!</string>
<string name="miband_firmware_unknown_warning">Ce micrologiciel n\'a pas été testé et peut ne pas être compatible avec Gadgetbridge.
\n
\nIl n\'est PAS conseillé de le flasher!</string>
<string name="fw_upgrade_notice_miband4">Vous êtes sur le point d\'installer le firmware %s sur votre Mi Band 4.
\n
\nVeuillez vous assurez d\'installer le fichier .fw, et après que le fichier .res. Votre bracelet redémarrera après l\'installation du fichier .fw.
\n
\nRemarque : Vous n\'avez pas à installer .res s\'il est exactement le même que celui précédemment installé.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS!</string>
<string name="fw_upgrade_notice_miband3">Vous allez installer le micrologiciel %s dans votre Mi Band 3.
\n
\nAssurez-vous d\'installer d\'abord le fichier .fw, et ensuite le fichiers .res. Votre bracelet redémarrera après l\'installation du fichiers .fw.
\n
\nRemarque : Vous n\'avez pas besoin d\'installer le fichier .res si c\'est exactement le même que celui déjà installé.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS!</string>
<string name="fw_upgrade_notice_amazfitgts">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTS.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS!</string>
<string name="fw_upgrade_notice_amazfitgtr">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTR.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS!</string>
<string name="fw_upgrade_notice_amazfitcor2">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor 2.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du .fw.
\n
\nNote : il n\'est pas nécessaire d\'installer le fichier .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES ET PÉRILS!
\n
\nNON TESTÉ, IL PEUT ÊTRE NÉCESSAIRE DE FLASHER UN MICROLOGICIEL BEATS_W SI LE NOM DE L\'APPAREIL EST « Amazfit Band 2 »</string>
<string name="fw_upgrade_notice_amazfitcor">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du .fw.
\n
\nNote : vous ne devez pas installer .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES ET PÉRILS!</string>
<string name="fw_upgrade_notice_amazfitbip_lite">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Bip Lite.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer le fichier .res si c\'est exactement le même que celui installé précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS!</string>
<string name="fw_upgrade_notice_amazfitbip">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Bip.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res, puis le fichier.gps.. Votre montre redémarrera après installation du .fw.
\n
\nNote : vous ne devez pas installer les fichiers .res et .gps si ceux-ci sont identiques à ceux installés précédemment.
\n
\nCONTINUEZ À VOS RISQUES ET PÉRILS!</string>
<string name="controlcenter_delete_device_dialogmessage">Ceci va supprimer lappareil et toutes les données associées!</string>
<string name="watch9_time_hours">Heures :</string>
<string name="watch9_time_minutes">Minutes :</string>
<string name="activity_db_management_empty_db_warning">Attention! En cliquant sur ce bouton, vous supprimerez toutes vos données et recommencerez à zéro.</string>
<string name="live_activity_max_heart_rate">Mesure cardiaque actuelle / maximum : %1$d / %2$d</string>
<string name="overstep">Trop d\'activité : %1$d</string>
<string name="lack_of_step">Manque d\'activité : %1$d</string>
<string name="overslept">Excès de sommeil : %1$s</string>
<string name="lack_of_sleep">Manque de sommeil : %1$s</string>
<string name="zetime_activity_tracking_summary">Activer le suivi des activités : comptera vos pas, etc.</string>
<string name="pref_summary_pebble_forceprotocol">Cette option force l\'utilisation du protocole de notification le plus récent selon votre version du micrologiciel. À VOS RISQUES ET PÉRILS!</string>
<string name="pref_summary_location_keep_uptodate">Essayer de garder la localisation à jour pendant le fonctionnement, sinon utiliser lemplacement enregistré</string>
<string name="hr_widget_calories">Calories</string>
<string name="appwidget_text">Zzz</string>
<string name="menuitem_alipay">Alipay</string>
<string name="devicetype_amazfit_gts">Amazfit GTS</string>
<string name="devicetype_makibes_hr3">Makibes HR3</string>
<string name="devicetype_mijia_lywsd02">Mijia Smart Clock</string>
<string name="devicetype_itag">iTag</string>
<string name="devicetype_miscale2">Mi Scale 2</string>
<string name="devicetype_casiogb6900">Casio GB-6900</string>
<string name="devicetype_roidmi3">Roidmi 3</string>
<string name="devicetype_roidmi">Roidmi</string>
<string name="devicetype_watch9">Watch 9</string>
<string name="devicetype_mykronoz_zetime">MyKronoz ZeTime</string>
<string name="devicetype_qhybrid">Fossil Q Hybrid</string>
<string name="devicetype_xwatch">XWatch</string>
<string name="devicetype_teclast_h30">Teclast H30</string>
<string name="devicetype_exrizu_k8">Exrizu K8</string>
<string name="devicetype_makibes_f68">Makibes F68</string>
<string name="devicetype_hplus">HPlus</string>
<string name="devicetype_liveview">LiveView</string>
<string name="devicetype_vibratissimo">Vibratissimo</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="devicetype_amazfit_gtr">Amazfit GTR</string>
<string name="devicetype_amazfit_cor2">Amazfit Cor 2</string>
<string name="devicetype_amazfit_cor">Amazfit Cor</string>
<string name="devicetype_amazfit_bip_lite">Amazfit Bip Lite</string>
<string name="devicetype_amazfit_bip">Amazfit Bip</string>
<string name="devicetype_miband4">Mi Band 4</string>
<string name="devicetype_miband3">Mi Band 3</string>
<string name="devicetype_miband2">Mi Band 2</string>
<string name="devicetype_miband">Mi Band</string>
<string name="devicetype_pebble">Pebble</string>
<string name="title_activity_vibration">Vibration</string>
<string name="calories">Calories</string>
<string name="miband_prefs_vibration">Vibration</string>
<string name="vibration_profile_long">Long</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="app_name">Gadgetbridge</string>
<plurals name="widget_alarm_target_hours">
<item quantity="one">%d heure</item>
<item quantity="other">%d heures</item>
</plurals>
<string name="pref_qhybrid_title_widget_draw_circles">Tracer les cercles Widget</string>
<string name="pbwinstallhandler_app_item">%1$s (%2$s)</string>
<string name="installhandler_firmware_name">%1$s: %2$s %3$s</string>
<string name="notif_battery_low_extended">%1$s pile faible : %2$s</string>
<string name="notif_battery_low">%1$s pile faible</string>
<string name="notif_battery_low_percent">%1$s pile restante : %2$s%%</string>
<string name="device_with_rssi">%1$s (%2$s)</string>
<string name="appversion_by_creator">%1$s par %2$s</string>
<string name="pref_header_auto_fetch">Récupération automatique</string>
<string name="pref_title_relax_firmware_checks">Activez cette option si vous souhaitez flasher un microprogramme qui n\'est pas destiné à votre appareil (à vos propres risques)</string>
<string name="pref_summary_relax_firmware_checks">Assouplir les contrôles des microprogrammes</string>
<string name="pref_title_vibration_strength">Puissance du vibreur</string>
<string name="pref_title_lower_button_function">Bouton inférieur</string>
<string name="pref_title_middle_button_function">Bouton du milieu</string>
<string name="pref_title_upper_button_function">Bouton supérieur</string>
<string name="hr_appname_commute">Trajet</string>
<string name="hr_appname_stopwatch">Chronomètre</string>
<string name="hr_appname_workout">Entraînement</string>
<string name="hr_appname_wellness">Bien-être</string>
<string name="pref_summary_custom_deviceicon">Afficher une icône de notification Android spécifique à l\'appareil à la place de l\'icône Gadgetbridge lors de la connexion</string>
<string name="pref_title_custom_deviceicon">Afficher licône de notification spécifique à lappareil</string>
<string name="notification_channel_high_priority_name">Priorité haute des notifications Gadgetbridge</string>
<string name="find_my_phone_notification">Trouver mon téléphone</string>
<string name="pref_summary_force_white_color_scheme">Utile si votre montre a les mains noires</string>
<string name="pref_title_force_white_color_scheme">Forcer le noir sur le blanc</string>
<string name="hr_widget_nothing">Rien</string>
<string name="hr_widget_weather">Météo</string>
<string name="hr_widget_active_minutes">Les minutes actives</string>
<string name="hr_widget_date">Date</string>
<string name="hr_widget_steps">Étapes</string>
<string name="hr_widget_heart_rate">Fréquence cardiaque</string>
<string name="pref_title_sync_caldendar">Sync calendrier des événements</string>
<string name="pref_summary_sync_calendar">Permet les alertes de calendrier, même en cas de déconnexion</string>
<string name="pref_summary_allow_high_mtu">Augmente la vitesse de transfert, mais peut ne pas fonctionner avec quelques appareils Android.</string>
<string name="pref_title_allow_high_mtu">Autoriser une grande MTU</string>
<string name="error_no_location_access">L\'accès à la localisation doit être autorisé et activé pour permettre à la détection de fonctionner correctement</string>
<string name="alarm_snooze">Reporter</string>
<string name="prefs_button_long_press_action_selection_title">Action d\'appui long de bouton</string>
<string name="prefs_button_variable_actions">Paramètres détaillés des appuis de bouton</string>
<string name="prefs_button_triple_press_action_selection_title">Action de l\'évènement 3</string>
<string name="prefs_button_double_press_action_selection_title">Action de l\'évènement 2</string>
<string name="prefs_button_single_press_action_selection_title">Action de l\'évènement 1</string>
<string name="devicetype_y5">Y5</string>
<string name="devicetype_banglejs">Bangle.js</string>
<string name="pref_summary_disable_new_ble_scanning">Cochez cette option si votre appareil ne peut être découvert</string>
<string name="pref_disable_new_ble_scanning">Désactiver la nouvelle détection BLE</string>
<string name="qhybrid_offset_time_by">décale l\'heure de</string>
<string name="qhybrid_changes_delay_prompt">le changement peut prendre quelques secondes…</string>
<string name="qhybrid_offset_timezone">décale le fuseau horaire de</string>
<string name="qhybrid_buttons_overwrite_error">Une erreur est survenue lors de la modification des boutons</string>
<string name="qhybrid_buttons_overwrite_success">Boutons modifiés</string>
<string name="qhybrid_prompt_million_steps">Veuillez régler le compteur de pas à un million pour l\'activer.</string>
<string name="qhybrid_use_activity_hand_as_notification_counter">utilise l\'activité de la main comme compteur de notification</string>
<string name="qhybrid_overwrite_buttons">modifier les boutons</string>
<string name="qhybrid_second_timezone_offset_relative_to_utc">décalage du deuxième fuseau horaire par rapport à UTC</string>
<string name="qhybrid_time_shift">décalage horaire</string>
<string name="qhybrid_goal_in_steps">Objectif de pas</string>
<string name="qhybrid_vibration_strength">Puissance de vibration :</string>
<string name="watch_not_connected">Montre non connectée</string>
<string name="preferences_qhybrid_settings">Paramètres hybrides Q</string>
<string name="pref_chart_sleep_rolling_24_off">De midi à midi</string>
<string name="pref_chart_sleep_rolling_24_on">Dernières 24 heures</string>
<string name="pref_title_chart_sleep_rolling_24_hour">Plage de sommeil</string>
<string name="pref_title_chart_heartrate_color">Couleur du rythme cardiaque</string>
<string name="pref_chart_heartrate_color_orange">Orange</string>
<string name="pref_chart_heartrate_color_red">Rouge</string>
<string name="discovery_need_to_enter_authkey">Cet appareil a besoin d\'une clé d\'auth. Pression longue sur celui-ci pour la saisir. Lisez le wiki.</string>
<string name="maximum_duration">Durée</string>
<string name="prefs_find_phone_duration">Durée de la sonnerie en secondes</string>
<string name="prefs_find_phone_summary">Utilisez votre bande pour lire l\'alarme de votre téléphone.</string>
<string name="prefs_enable_find_phone">Activer « Trouver le tél. »</string>
<string name="prefs_find_phone">Trouver le téléphone</string>
<string name="preferences_makibes_hr3_settings">Réglages Makibes HR3</string>
<string name="activity_error_no_app_for_gpx">Pour visualiser votre géolocalisation, installez une appli qui lit les fichiers GPX.</string>
<string name="pref_display_add_device_fab_off">Visible uniquement si aucun appareil n\'est ajouté</string>
<string name="pref_display_add_device_fab_on">Toujours visible</string>
<string name="pref_display_add_device_fab">Bouton pour connecter un nouvel appareil</string>
<string name="widget_1_hour">1 heure</string>
<string name="widget_20_minutes">20 minutes</string>
<string name="widget_10_minutes">10 minutes</string>
<string name="widget_5_minutes">5 minutes</string>
<string name="widget_set_alarm_after">Définir l\'alarme après :</string>
<string name="widget_listing_label">État et alarmes</string>
<string name="widget_sleep_label">Sommeil : %1$s</string>
<string name="widget_steps_label">Pas : %1$02d</string>
<string name="appwidget_sleep_alarm_widget_label">Réveil</string>
<string name="activity_db_management_exportimport_label">Exporter et Importer</string>
<string name="activity_db_management_empty_DB">Vider la base de données</string>
<string name="activity_DB_empty_button">Vider la base de données</string>
<string name="activity_DB_delete_legacy_button">Supprimer l\'ancienne base de données</string>
<string name="activity_DB_test_export_message">Exportation de la base de données…</string>
<string name="activity_DB_test_export_button">Lancer immédiatement l\'exportation automatique</string>
<string name="activity_DB_import_button">Importer la base de données</string>
<string name="activity_DB_ExportButton">Exporter la base de données</string>
<string name="activity_db_management_autoexport_label">Exportation automatique</string>
<string name="activity_db_management_autoexport_explanation">L\'export automatique des données est réglé vers :</string>
<string name="pref_summary_use_custom_font">Activer ceci afin dafficher les émojis si votre appareil a un micrologiciel de police personnalisée</string>
<string name="pref_title_use_custom_font">Utiliser une police personnalisée</string>
<string name="pref_title_expose_hr">Accès tiers fréq. cardiaque</string>
<string name="pref_summary_expose_hr">Permettre aux autres applis d\'accéder aux données de fréquence cardiaque en temps réel lorsque Gadgetbridge est connecté</string>
<string name="menuitem_nfc">NFC</string>
<string name="weeksleepchart_sleep_a_month">Sommeil par mois</string>
<string name="weekstepschart_steps_a_month">Pas par mois</string>
<string name="pref_charts_range_off">Gamme des graphiques positionnée sur une semaine</string>
<string name="pref_charts_range_on">Gamme des graphiques positionnée sur un mois</string>
<string name="pref_title_charts_range">Gamme des graphiques</string>
<string name="pref_title_charts_average">Afficher les moyennes dans les graphiques</string>
<string name="pref_header_charts">Paramètres graphiques</string>
<string name="average">Moyenne : %1$s</string>
<string name="prefs_hr_alarm_high">Limite haute</string>
<string name="prefs_hr_alarm_low">Limite basse</string>
<string name="prefs_hr_alarm_activity">Alarme de la fréquence cardiaque durant une activité sportive</string>
<string name="portuguese">Portugais</string>
<string name="vietnamese">Vietnamien</string>
<string name="thai">Thaïlandais</string>
<string name="indonesian">Indonésien</string>
<string name="arabic">Arabe</string>
<string name="ukrainian">Ukrainien</string>
<string name="turkish">Turc</string>
<string name="dutch">Néerlandais</string>
<string name="devicetype_bfh16">BFH-16</string>
<string name="pref_summary_authkey">Changez la clé auteur à une clé générale sur tous vos appareils Android sur lesquels vous souhaitez vous connecter. La précédente clé par défaut était 0123456789@ABCDE</string>
<string name="mi3_prefs_night_mode">Mode nuit</string>
<string name="minutes_30">30 minutes</string>
<string name="minutes_10">10 minutes</string>
<string name="minutes_5">5 minutes</string>
<string name="minutes_1">1 minute</string>
<string name="seconds_30">30 secondes</string>
<string name="seconds_20">20 secondes</string>
<string name="seconds_10">10 secondes</string>
<string name="seconds_5">5 secondes</string>
<string name="no_limit">Sans limite</string>
<string name="pref_title_notifications_timeout">Durée minimum entre deux notifications</string>
<string name="norwegian_bokmal">Bokmål norvégien</string>
<string name="you_did_not_sleep">Vous n\'avez pas dormi</string>
<string name="you_slept">Vous avez dormi de %1$s à %2$s</string>
<string name="japanese">Japonais</string>
<string name="korean">Koréen</string>
<string name="polish">Polonais</string>
<string name="french">Français</string>
<string name="italian">Italien</string>
<string name="german">Allemand</string>
<string name="mi3_prefs_band_screen_unlock_summary">Glisser le doigt vers le haut pour débloquer l\'écran du bracelet</string>
<string name="mi3_prefs_band_screen_unlock">Déverrouillage de l\'écran du Band</string>
<string name="title_activity_watch9_calibration">Calibration de la Watch 9</string>
<string name="title_activity_watch9_pairing">Appairage de la Watch 9</string>
<string name="watch9_calibration_button">Calibrer</string>
<string name="watch9_calibration_hint">Régler l\'heure que votre appareil indique actuellement.</string>
<string name="watch9_pairing_tap_hint">Lorsque votre bracelet vibre, secouez-le ou pressez son bouton.</string>
<string name="controlcenter_calibrate_device">Calibrer l\'appareil</string>
<string name="menuitem_music">Musique</string>
<string name="menuitem_more">Suite</string>
<string name="menuitem_notifications">Notifications</string>
<string name="devicetype_id115">ID115</string>
<string name="vertical">Vertical</string>
<string name="horizontal">Horizontal</string>
<string name="prefs_screen_orientation">Orientation de l\'écran</string>
<string name="russian">Russe</string>
<string name="pref_auto_fetch_limit_fetches_summary">Synchronisation toutes les %d minutes</string>
<string name="pref_auto_fetch_limit_fetches">Temps minimum entre synchronisations</string>
<string name="pref_auto_fetch">Récupérer automatiquement les données d\'activité</string>
<string name="whitelist_all_for_notifications">Mettre toutes les notifications en liste blanche</string>
<string name="blacklist_all_for_notifications">Mettre toutes les notifications en liste noire</string>
<string name="devicetype_q8">Q8</string>
<string name="menuitem_shortcut_weather">Météo (Raccourci)</string>
<string name="menuitem_shortcut_alipay">Alipay (Raccourci)</string>
<string name="pref_summary_pebble_gatt_clientonly">C\'est uniquement pour les Pebble 2 et expérimental, à essayer si vous avez des problèmes de connectivité</string>
<string name="pref_title_pebble_gatt_clientonly">client GATT uniquement</string>
<string name="menuitem_settings">Réglages</string>
<string name="menuitem_compass">Boussole</string>
<string name="menuitem_timer">Minuteur</string>
<string name="menuitem_alarm">Alarme</string>
<string name="menuitem_weather">Météo</string>
<string name="menuitem_activity">Activité</string>
<string name="menuitem_status">Etat</string>
<string name="reset_index">Réinitialiser la date de récupération</string>
<string name="share">Partager</string>
<string name="select_all">Tout sélectionner</string>
<string name="pref_title_audio_player">Lecteur audio préféré</string>
<string name="pref_title_general_autoreconnect">Reconnexion automatique</string>
<string name="activity_type_treadmill">Tapis de course</string>
<string name="activity_type_biking">Vélo</string>
<string name="activity_summaries">Activités</string>
<string name="activity_type_unknown">Activité inconnue</string>
<string name="activity_type_swimming">Natation</string>
<string name="hr_widget_battery">Pile</string>
<string name="battery">Pile</string>
<string name="notif_battery_low_title">Niveau de la pile faible!</string>
<string name="pref_summary_pebble_enable_bgjs">Si activé, autorise l\'affichage de la météo, niveau de la pile, etc.</string>
<string name="warning">Attention!</string>
<string name="watch9_time_seconds">Secondes :</string>
<string name="activity_type_walking">Marche</string>
<string name="activity_type_running">Course</string>
<string name="activity_type_not_worn">Dispositif non utilisé</string>
<string name="activity_type_deep_sleep">Sommeil profond</string>
<string name="activity_type_light_sleep">Sommeil léger</string>
<string name="activity_type_activity">Activité</string>
<string name="activity_type_not_measured">Non mesurée</string>
<string name="controlcenter_start_activity_tracks">Suivi de vos activités</string>
<string name="on">Actif</string>
<string name="notification_channel_name">Notifications de Gadgetbridge</string>
<string name="spanish">Espagnol</string>
<string name="choose_auto_export_location">Choisissez l\'emplacement d\'exportation</string>
<string name="pref_summary_auto_export_interval">Exporter toutes les %d heures</string>
<string name="pref_title_auto_export_interval">Intervalle d\'exportation</string>
<string name="pref_title_auto_export_location">Emplacement de l\'exportation</string>
<string name="pref_title_auto_export_enabled">Exportation automatique activée</string>
<string name="pref_header_auto_export">Exporter automatiquement</string>
<string name="pref_title_weather">Météo</string>
<string name="devicetype_no1_f1">No.1 F1</string>
<string name="devicetype_test">Appareil de test</string>
<string name="devicetype_unknown">Appareil inconnu</string>
<string name="kind_watchface">Cadran</string>
<string name="kind_resources">Ressources</string>
<string name="kind_gps_cep">Correction d\'erreurs GPS</string>
<string name="kind_gps_almanac">Almanach GPS</string>
<string name="kind_gps">Micrologiciel GPS</string>
<string name="kind_font">Police</string>
<string name="kind_invalid">Données non valides</string>
<string name="kind_firmware">Micrologiciel</string>
<string name="pref_title_weather_location">Emplacement météo (CM/LOS)</string>
<string name="interval_one_hour">Une fois par heure</string>
<string name="interval_thirty_minutes">Toutes les 30 minutes</string>
<string name="interval_ten_minutes">Toutes les 10 minutes</string>
<string name="interval_five_minutes">Toutes les 5 minutes</string>
<string name="interval_one_minute">Une fois par minute</string>
<string name="prefs_title_heartrate_measurement_interval">Mesure du pouls toute la journée</string>
<string name="english">Anglais</string>
<string name="traditional_chinese">Chinois traditionnel</string>
<string name="simplified_chinese">Chinois simplifié</string>
<string name="automatic">Automatique</string>
<string name="pref_title_charts_swipe">Permettre le balayage gauche/droite dans les graphiques d\'activité</string>
<string name="controlcenter_connect">Connexion…</string>
<string name="activity_web_view">Activité Web View</string>
<string name="pref_title_pebble_enable_bgjs">Activer tâche de fond JS</string>
<string name="_pebble_watch_reply">Répondre</string>
<string name="_pebble_watch_mute">Silencieux</string>
<string name="_pebble_watch_open_on_phone">Ouvrir sur le smartphone Android</string>
<string name="mi2_prefs_button_press_count_max_delay_summary">Délai maximum entre pressions en millisecondes</string>
<string name="mi2_prefs_button_press_count_max_delay">Délai maximum entre pressions</string>
<string name="mi2_prefs_button_action_vibrate_summary">Activer la vibration après déclenchement de l\'action</string>
<string name="mi2_prefs_button_action_vibrate">Activer la vibration du bracelet</string>
<string name="mi2_prefs_button_action_summary">Activer action après nombre spécifié de pressions</string>
<string name="mi2_prefs_button_action">Activer action du bouton</string>
<string name="mi2_prefs_button_press_broadcast_summary">Message de diffusion envoyé avec l\'évènement. Le paramètre « button_id » est automatiquement ajouté à chaque message.</string>
<string name="mi2_prefs_button_press_broadcast">Message à envoyer</string>
<string name="mi2_prefs_button_press_count_summary">Nombre d\'appuis sur le boutton pour envoyer lÉvènement 1. Appuyer de nouveau autant de fois créera l\'Évènement 2, etc.</string>
<string name="mi2_prefs_button_press_count">Nombre de pressions du bouton</string>
<string name="mi2_prefs_button_actions_summary">Spécifier les actions par pression du bouton</string>
<string name="mi2_prefs_button_actions">Actions du bouton</string>
<string name="discovery_dont_pair">Ne pas appairer</string>
<string name="discovery_yes_pair">Appairer</string>
<string name="discovery_pair_question">Sélectionnez Jumeler pour associer vos dispositifs. Si cela échoue, essayez à nouveau sans jumelage.</string>
<string name="discovery_successfully_bonded">Lié à %1$s.</string>
<string name="discovery_enable_bluetooth">Activez le Bluetooth pour trouver des dispositifs.</string>
<string name="discovery_trying_to_connect_to">Tentative de connexion à : %1$s</string>
<string name="discovery_bonding_failed_immediately">Le lien avec %1$s a échoué instantanément.</string>
<string name="discovery_attempting_to_pair">Tentative de jumelage avec %1$s</string>
<string name="mi2_dnd_scheduled">Programmé (intervalle de temps)</string>
<string name="mi2_dnd_automatic">Automatique (détection de sommeil)</string>
<string name="mi2_dnd_off">Éteint</string>
<string name="off">Éteint</string>
<string name="mi2_enable_text_notifications_summary">Requis : micrologiciel version 1.0.1.28 ou plus, fichier Mili_pro.ft* installé.</string>
<string name="mi2_enable_text_notifications">Notifications textuelles</string>
<string name="miband2_prefs_timeformat">Mi2 : format de l\'heure</string>
<string name="StringUtils_sender">(%1$s)</string>
<string name="pref_screen_notification_profile_alarm_clock">Réveil</string>
<string name="timeformat_am_pm">AM/PM</string>
<string name="timeformat_24h">24H</string>
<string name="unit_imperial">Impériale</string>
<string name="unit_metric">Métrique</string>
<string name="pref_summary_setup_bt_pairing">Désactivez ceci si vous avez des problèmes de connexion</string>
<string name="pref_title_setup_bt_pairing">Activer le jumelage Bluetooth</string>
<string name="weather_notification_label">Assurez vous que ce thème soit activé dans l\'application de notification de la météo pour recevoir les informations sur votre Pebble.
\n
\nAucune configuration n\'est requise.
\n
\nVous pouvez activer l\'application météo système de votre Pebble depuis la configuration de l\'application.
\n
\nLes watchfaces supportées afficheront la météo automatiquement.</string>
<string name="pebble_pairing_hint">Une fenêtre de jumelage va safficher sur votre téléphone. Si cela ne se produit pas, regardez dans vos notifications et acceptez-la. Acceptez ensuite la demande de jumelage sur votre Pebble.</string>
<string name="title_activity_pebble_pairing">Jumelage avec une Pebble</string>
<string name="Delete">Supprimer</string>
<string name="Cancel">Annuler</string>
<string name="dbmanagementactivity_overwrite">Écraser</string>
<string name="dbmanagementactivity_old_activity_db_deletion_failed">Échec de la destruction de l\'ancienne base de données.</string>
<string name="dbmanagementactivity_old_activity_db_successfully_deleted">Les anciennes données d\'activité ont été effacées.</string>
<string name="dbmanagementactivity_db_deletion_failed">Échec de la destruction de la base de données.</string>
<string name="dbmanagementactivity_database_successfully_deleted">Les données ont été effacées.</string>
<string name="dbmanagementactivity_error_importing_shared">Erreur d\'importation des préférences : %1$s</string>
<string name="dbmanagementactivity_error_importing_db">Erreur lors de l\'importation de la base de données : %1$s</string>
<string name="dbmanagementactivity_import_successful">Importé.</string>
<string name="dbmanagementactivity_error_exporting_shared">Erreur d\'exportation des préférences : %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">Erreur d\'exportation de la base de données : %1$s</string>
<string name="dbmanagementactivity_exported_to">Exporter vers : %1$s</string>
<string name="pref_title_pebble_health_store_raw">Stockez les enregistrements brut dans la base de données</string>
<string name="live_activity_heart_rate">Fréquence cardiaque</string>
<string name="charts_legend_heartrate">Fréquence cardiaque</string>
<string name="updatefirmwareoperation_firmware_not_sent">Échec lors de l\'écriture du micrologiciel</string>
<string name="updatefirmwareoperation_update_in_progress">Installation du micrologiciel</string>
<string name="DEVINFO_HR_VER">"Fréquence cardiaque : "</string>
<string name="error_creating_directory_for_logfiles">Erreur à la création de votre fichier log : %1$s</string>
<string name="device_fw">Version du micrologiciel : %1$s</string>
<string name="device_hw">Révision matérielle : %1$s</string>
<string name="activity_prefs_sleep_duration">Temps de sommeil préféré en heures</string>
<string name="add_widget">Ajouter un widget</string>
<string name="authentication_required">Authentification requise</string>
<string name="authenticating">Authentification</string>
<string name="activity_prefs_weight_kg">Poids en kg</string>
<string name="activity_prefs_height_cm">Taille en cm</string>
<string name="activity_prefs_gender">Sexe</string>
<string name="activity_prefs_year_birth">Année de naissance</string>
<string name="activity_prefs_about_you">À propos de vous</string>
<string name="waiting_for_reconnect">En attente de reconnexion</string>
<string name="FetchActivityOperation_about_to_transfer_since">Sur le point de transférer des données depuis %1$s</string>
<string name="mi2_prefs_do_not_disturb_end">Heure de fin</string>
<string name="mi2_prefs_do_not_disturb_start">Heure de début</string>
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Désactiver les alertes d\'inactivité pendant un intervalle de temps</string>
<string name="mi2_prefs_inactivity_warnings_threshold">Seuil d\'inactivité (en minutes)</string>
<string name="mi2_prefs_inactivity_warnings_summary">Le bracelet vibrera si vous n\'êtes pas actif pendant un moment</string>
<string name="mi2_prefs_inactivity_warnings">Alertes d\'inactivité</string>
<string name="mi2_prefs_do_not_disturb_summary">Le bracelet ne recevra pas de notifications si activé</string>
<string name="mi2_prefs_do_not_disturb">Ne Pas Déranger</string>
<string name="mi2_prefs_rotate_wrist_to_switch_info">Tournez votre poignet pour changer d\'élément</string>
<string name="mi2_prefs_activate_display_on_lift">Allumer l\'écran lors d\'un mouvement</string>
<string name="mi2_prefs_display_items_summary">Choisissez les éléments à afficher sur le bracelet</string>
<string name="mi2_prefs_display_items">Éléments à afficher</string>
<string name="mi2_prefs_goal_notification_summary">Le bracelet vibrera lorsque l\'objectif de pas quotidien sera atteint</string>
<string name="mi2_prefs_goal_notification">Notification d\'objectif</string>
<string name="dateformat_date_time">Date et heure</string>
<string name="dateformat_time">Heure</string>
<string name="miband2_prefs_dateformat">Format de la date</string>
<string name="miband_prefs_device_time_offset_hours">La compensation de temps en heure (pour travailleurs en rotation, par exemple)</string>
<string name="miband_prefs_hr_sleep_detection">Utiliser le capteur cardiaque pour améliorer la détection du sommeil</string>
<string name="miband_prefs_reserve_alarm_calendar">Alarmes à réserver pour événements futurs</string>
<string name="fwinstaller_firmware_not_compatible_to_device">Ce micrologiciel n\'est pas compatible avec l\'appareil</string>
<string name="miband_fwinstaller_incompatible_version">Micrologiciel non compatible</string>
<string name="pref_title_keep_data_on_device">Conserver les activités sur l\'appareil</string>
<string name="user_feedback_all_alarms_disabled">Toutes alarmes désactivées</string>
<string name="device_not_connected">Non connecté.</string>
<string name="abstract_chart_fragment_kind_not_worn">Non porté</string>
<string name="abstract_chart_fragment_kind_deep_sleep">Sommeil profond</string>
<string name="abstract_chart_fragment_kind_light_sleep">Sommeil léger</string>
<string name="abstract_chart_fragment_kind_activity">Activité</string>
<string name="live_activity_start_your_activity">Démarrez votre activité</string>
<string name="live_activity_steps_per_minute_history">Historique de pas/minute</string>
<string name="live_activity_total_steps">Nombre total de pas</string>
<string name="live_activity_current_steps_per_minute">Pas/minute actuel</string>
<string name="live_activity_steps_history">Historique de pas</string>
<string name="pref_summary_low_latency_fw_update">Cela peut aider sur les appareils où les installations de micrologiciel échouent.</string>
<string name="pref_title_low_latency_fw_update">Utilisez le mode basse latence pour installer un micrologiciel</string>
<string name="pref_summary_keep_data_on_device">Les données d\'activités seront conservées sur le Mi Band après la synchronisation. Utile si GB est utilisé avec d\'autres applications.</string>
<string name="pref_summary_dont_ack_transfers">Les données d\'activités ne seront pas effacées du bracelet si elles ne sont pas confirmées. Utile si GB est utilisé avec d\'autres applications.</string>
<string name="pref_title_dont_ack_transfer">Ne pas confirmer le transfert de données d\'activités</string>
<string name="weeksteps_today_steps_description">Nombre de pas aujourd\'hui, objectif : %1$s</string>
<string name="liveactivity_live_activity">Activité en direct</string>
<string name="heart_rate">Fréquence cardiaque</string>
<string name="clock">Horloge</string>
<string name="distance">Distance</string>
<string name="chart_steps">Pas</string>
<string name="updatefirmwareoperation_write_failed">Échec lors de l\'installation du micrologiciel</string>
<string name="updatefirmwareoperation_update_complete_rebooting">Installation complète du micrologiciel, redémarrage de l\'appareil…</string>
<string name="updatefirmwareoperation_update_complete">Installation complète du micrologiciel</string>
<string name="updatefirmwareoperation_metadata_updateproblem">Problème avec le transfert de métadonnées du micrologiciel</string>
<string name="pbwinstallhandler_correct_hw_revision">Version du matériel correcte</string>
<string name="pbw_installhandler_pebble_firmware">Micrologiciel Pebble %1$s</string>
<string name="fwappinstaller_connection_state">Connexion à l\'appareil : %1$s</string>
<string name="pref_title_authkey">Clé Auteur</string>
<string name="title_activity_device_specific_settings">Paramètres spécifiques de l\'appareil</string>
<string name="pref_title_support_voip_calls">Activer les applications d\'appel VoIP</string>
<string name="activity_prefs_activetime_minutes">Objectif quotidien : temps d\'activité en minutes</string>
<string name="activity_prefs_distance_meters">Objectif quotidien : distance en mètres</string>
<string name="activity_prefs_calories_burnt">Objectif quotidien : calories brulées</string>
<string name="interval_forty_five_minutes">Toutes les 45 min</string>
<string name="interval_fifteen_minutes">Toutes les 15 min</string>
<string name="pref_screen_notification_profile_anti_loss">Alerte Anti-Perte</string>
<string name="pref_screen_notification_profile_low_power">Alerte batterie faible</string>
<string name="pref_screen_notification_profile_inactivity">Notification d\'inactivité</string>
<string name="pref_screen_notification_profile_calendar">Notification du calendrier</string>
<string name="pref_screen_notification_profile_missed_call">Notification appel manqué</string>
<string name="zetime_signaling_vibrate_beep_once">Vibration et bip uniques</string>
<string name="zetime_signaling_beep_twice">Bip double</string>
<string name="zetime_signaling_beep_once">Bip unique</string>
<string name="zetime_signaling_vibrate_twice">Vibration double</string>
<string name="zetime_signaling_vibrate_once">Vibration unique</string>
<string name="zetime_signaling_vibrate_beep">Vibration et bip continus</string>
<string name="zetime_signaling_beep">Bip continu</string>
<string name="zetime_signaling_vibrate">Vibration continue</string>
<string name="zetime_signaling_none">Silencieux</string>
<string name="zetime_title_alarm_signaling">Type de signal pour l\'alarme</string>
<string name="zetime_prefs_inactivity_su">Dimanche</string>
<string name="zetime_prefs_inactivity_sa">Samedi</string>
<string name="zetime_prefs_inactivity_fr">Vendredi</string>
<string name="zetime_prefs_inactivity_th">Jeudi</string>
<string name="zetime_prefs_inactivity_we">Mercredi</string>
<string name="zetime_prefs_inactivity_tu">Mardi</string>
<string name="zetime_prefs_inactivity_mo">Lundi</string>
<string name="zetime_prefs_inactivity_repetitions">Répétitions</string>
<string name="zetime_date_format_3">mm/jj/aaaa</string>
<string name="zetime_date_format_2">jj/mm/aaaa</string>
<string name="zetime_date_format_1">aaaa/mm/jj</string>
<string name="zetime_date_format">Format de la date</string>
<string name="zetime_calories_type_all">Calories brûlées activement et au repos</string>
<string name="zetime_calories_type_active">Seulement les calories brûlées activement</string>
<string name="zetime_calories_type">Type de calories</string>
<string name="zetime_handmove_display_summary">Tourner le poignet pour activer ou désactiver l\'écran.</string>
<string name="zetime_handmove_display">Mouvement de la main</string>
<string name="zetime_activity_tracking">Suivi des Activités</string>
<string name="zetime_analog_mode_handsandsteps">Aiguilles et Pas</string>
<string name="zetime_analog_mode_hands">Aiguilles seulement</string>
<string name="zetime_analog_mode">Mode analogique</string>
<string name="activity_prefs_alarm_min_heart_rate">Fréquence cardiaque minimale</string>
<string name="activity_prefs_alarm_max_heart_rate">Fréquence cardiaque maximale</string>
<string name="zetime_heart_rate_alarm_enable">Activer l\'alarme de fréquence cardiaque</string>
<string name="zetime_title_heart_rate_alarm_summary">La montre vous alertera quand votre fréquence cardiaque dépasse les limites.</string>
<string name="zetime_title_heart_rate_alarm">Alarme Fréquence Cardiaque</string>
<string name="zetime_title_screentime">Durée d\'écran allumé en secondes</string>
<string name="zetime_title_heartrate">Paramètres Fréquence Cardiaque</string>
<string name="zetime_title_settings">Paramètres ZeTime</string>
<string name="prefs_disconnect_notification">Notification de déconnexion</string>
<string name="activity_type_exercise">Activité physique</string>
<string name="appwidget_not_connected">Non connecté, l\'alarme n\'est pas définie.</string>
<string name="save_configuration">Sauvegarder la configuration</string>
<string name="mode_configuration">Mode Configuration</string>
<string name="filter_mode">Mode Filtre</string>
<string name="toast_notification_filter_words_empty_hint">Veuillez entrer au moins un mot</string>
<string name="filter_submode_all">Tous les mots</string>
<string name="filter_submode_at_least_one">Au moins un des mots</string>
<string name="filter_mode_blacklist">Bloquer lorsque contient les mots</string>
<string name="filter_mode_whitelist">Montrer lorsque contient les mots</string>
<string name="filter_mode_none">Ne pas filtrer</string>
<string name="toast_notification_filter_saved_successfully">Filtre des notifications sauvegardé</string>
<string name="edittext_notification_filter_words_hint">Saisissez les mots désirés, chacun sur une ligne</string>
<string name="toast_app_must_not_be_blacklisted">L\'application ne doit pas être en liste noire pour pouvoir être configurée</string>
<string name="title_activity_notification_filter">Filtre de notifications</string>
<string name="appwidget_setting_alarm">Une alarme a été enregistré pour %1$02d:%2$02d</string>
<string name="debugactivity_really_factoryreset">Une réinitialisation effacera toutes les données de l\'appareil connecté (si supporté). Les appareils Xiaomi/Huami modifient également l\'adresse MAC Bluetooth, de sorte qu\'ils apparaissent comme de nouveaux appareils dans Gadgetbridge.</string>
<string name="no_data">Pas de données</string>
<string name="language_and_region_prefs">Paramètres de langue et de région</string>
<string name="preferences_rtl_settings">Support Droite-à-Gauche</string>
<string name="pref_summary_contextual_arabic">A cocher pour activer le support \"Arabe contextuel\"</string>
<string name="pref_title_contextual_arabic">Arabe contextuel</string>
<string name="pref_rtl_max_line_length_summary">Allonge ou raccourcis les lignes dans les textes écrits de droite à gauche</string>
<string name="pref_rtl_max_line_length">Longueur max. d\'une ligne en mode Droite-à-Gauche</string>
<string name="pref_summary_rtl">Cocher ceci si votre appareil n\'est pas compatible avec les langues \"droite-à-gauche\"</string>
<string name="pref_title_rtl">De droite à gauche</string>
<string name="activity_prefs_chart_min_heart_rate">Fréquence cardiaque minimum</string>
<string name="activity_prefs_chart_max_heart_rate">Fréquence cardiaque maximum</string>
<string name="activity_prefs_charts">Paramètres des graphiques</string>
<string name="pref_invalid_frequency_message">Veuillez introduire une fréquence entre 87.5 et 108.0</string>
<string name="pref_invalid_frequency_title">Fréquence non-valide</string>
<string name="preferences_fm_frequency">Fréquence FM</string>
<string name="preferences_led_color">Couleur de la DEL</string>
<string name="controlcenter_change_fm_frequency">Changer la fréquence FM</string>
<string name="controlcenter_change_led_color">Changer la couleur de la DEL</string>
<string name="share_log_warning">Veuillez garder à l\'esprit que les fichiers logs de Gadgetbridge peuvent contenir des tas d\'informations personnelles, incluant entre autre des données relatives à la santé, des identifiants uniques (telles que des adresses MAC), des préférences musicales, etc. Pensez à modifier le fichier et retirer ces informations personnelles avant toute publication sur un rapport de bug public.</string>
<string name="share_log">Partager les logs</string>
<string name="ok">Ok</string>
<string name="mi3_night_mode_sunset">Au coucher du soleil</string>
<string name="mi3_prefs_night_mode_summary">Diminuer la luminosité de l\'écran du bracelet automatiquement lorsqu\'il fait sombre</string>
<string name="miband_fwinstaller_compatible_version">Version compatible</string>
<string name="fwapp_install_device_not_ready">Le fichier ne peut pas être installé, l\'appareil n\'est pas prêt.</string>
<string name="updating_firmware">Installation du micrologiciel…</string>
<string name="activity_sleepchart_activity_and_sleep">Activité</string>
<string name="weekstepschart_steps_a_week">Pas de la semaine</string>
<string name="weeksleepchart_today_sleep_description">Sommeil aujourd\'hui, objectif : %1$s</string>
<string name="weeksleepchart_sleep_a_week">Sommeil de la semaine</string>
<string name="sleepchart_your_sleep">Sommeil</string>
<string name="notif_battery_low_bigtext_number_of_charges">Nombre de charges : %s</string>
<string name="notif_battery_low_bigtext_last_charge_time">Dernière charge : %s
\n</string>
<string name="installer_activity_wait_while_determining_status">Veuillez patienter pendant la détermination de l\'état de l\'installation…</string>
<string name="pbw_install_handler_hw_revision_mismatch">Impossible d\'installer le micrologiciel spécifié : il ne correspond pas à la version du matériel de votre Pebble.</string>
<string name="pbw_install_handler_unable_to_install">Impossible d\'installer le ficher suivant : %1$s</string>
<string name="installer_activity_unable_to_find_handler">Impossible de trouver un gestionnaire pour installer ce fichier.</string>
<string name="cannot_connect">Impossible de se connecter : %1$s</string>
<string name="controlcenter_start_activitymonitor">Votre activité (ALPHA)</string>
<string name="dbaccess_error_executing">Erreur lors de lexécution de %1$s\'</string>
<string name="miband_prefs_fitness_goal">Objectif de pas par jour</string>
<string name="user_feedback_miband_activity_data_transfer">Sur le point de transférer %1$s de données à partir de %2$s</string>
<string name="user_feedback_miband_set_alarms_ok">Alarmes envoyées à l\'appareil.</string>
<string name="user_feedback_miband_set_alarms_failed">Une erreur s\'est produite lors du paramétrage des alarmes, veuillez réessayer.</string>
<string name="alarm_smart_wakeup">Réveil intelligent</string>
<string name="alarm_sat_short">Sam</string>
<string name="alarm_fri_short">Ven</string>
<string name="alarm_thu_short">Jeu</string>
<string name="alarm_wed_short">Mer</string>
<string name="alarm_tue_short">Mar</string>
<string name="alarm_mon_short">Lun</string>
<string name="alarm_sun_short">Dim</string>
<string name="title_activity_alarm_details">Détails des alarmes</string>
<string name="controlcenter_start_configure_alarms">Configurer les alarmes</string>
<string name="title_activity_set_alarm">Configurer les alarmes</string>
<string name="title_activity_charts">Activité et Sommeil</string>
<string name="control_center_cancel_to_stop_vibration">Annuler pour arrêter les vibrations.</string>
<string name="control_center_find_lost_device">Trouver l\'appareil perdu</string>
<string name="stats_y_axis_label">Pas par minute</string>
<string name="stats_x_axis_label">Total de minutes</string>
<string name="stats_title">Zones de vitesse</string>
<string name="pref_screen_notification_profile_generic_social">Réseau social</string>
<string name="pref_screen_notification_profile_generic_navigation">Navigation</string>
<string name="pref_screen_notification_profile_generic_chat">Tchat</string>
<string name="pref_screen_notification_profile_incoming_call">Notification d\'appels entrants</string>
<string name="pref_screen_notification_profile_email">Notification par courriel</string>
<string name="pref_screen_notification_profile_generic">Notification générique</string>
<string name="pref_header_vibration_settings">Paramètres des vibrations</string>
<string name="pref_screen_notification_profile_sms">Notification Texto</string>
<string name="vibration_try">Essayer</string>
<string name="vibration_profile_alarm_clock">Réveil</string>
<string name="vibration_profile_ring">Sonnette</string>
<string name="vibration_profile_waterdrop">Goute d\'eau</string>
<string name="vibration_profile_medium">Moyen</string>
<string name="vibration_profile_short">Court</string>
<string name="vibration_profile_staccato">Saccadé</string>
<string name="pref_screen_vibration_profile">Profil de vibration</string>
<string name="sleep_activity_date_range">De %1$s à %2$s</string>
<string name="busy_task_fetch_activity_data">Récupération des données d\'activité</string>
<string name="initializing">Initialisation</string>
<string name="pref_write_logfiles">Écrire des fichiers journaux</string>
<string name="title_activity_sleepmonitor">Moniteur de sommeil</string>
<string name="pref_header_vibration_count">Nombre de vibrations</string>
<string name="miband_prefs_alias">Nom/Pseudo</string>
<string name="candidate_item_device_image">Image de l\'appareil</string>
<string name="discovery_note">Note :</string>
<string name="discovery_connected_devices_hint">Mettez votre appareil en mode visible. Les appareils déjà connectés ne seront pas visibles. Sur Android 6 ou supérieur, vous devez activer la localisation (ex. GPS). Désactivez Privacy Guard pour Gadgetbridge, il pourrait stopper et redémarrer votre téléphone. Si votre appareil n\'est pas visible après 2 minutes, réessayez après avoir redémarré votre téléphone.</string>
<string name="appinstaller_install">Installer</string>
<string name="miband_pairing_tap_hint">Quand votre Mi Band vibre et clignote, appuyez dessus plusieurs fois d\'affilée.</string>
<string name="miband_pairing_using_dummy_userdata">Aucune donnée utilisateur valide fournie, utilisation de données fictives pour le moment.</string>
<string name="right">Droite</string>
<string name="left">Gauche</string>
<string name="other">Autre</string>
<string name="female">Femme</string>
<string name="male">Homme</string>
<string name="preferences_miband_settings">Paramètres Mi Band / Amazfit</string>
<string name="preferences_category_device_specific_settings">Paramètres spécifiques à l\'appareil</string>
<string name="message_cannot_pair_no_mac">Aucune adresse MAC fournie, ne peut être appairé.</string>
<string name="pairing_already_bonded">Déjà lié avec %1$s (%2$s), connexion…</string>
<string name="pairing_in_progress">Création du lien en cours : %1$s (%2$s)</string>
<string name="pairing_unable_to_pair_with">Impossible se sappairer avec %1$s (%2$s)</string>
<string name="pairing_creating_bond_with">Création dun lien avec %1$s (%2$s)</string>
<string name="pairing">Jumelage avec %s…</string>
<string name="title_activity_mi_band_pairing">Appairer votre Mi Band</string>
<string name="android_pairing_hint">Utiliser l\'appairage Bluetooth d\'Android pour jumeler l\'appareil.</string>
<string name="title_activity_android_pairing">Appairer l\'appareil</string>
<string name="action_discover">Connecter un nouvel appareil</string>
<string name="discovery_start_scanning">Démarrer le scan</string>
<string name="discovery_stop_scanning">Arrêter le scan</string>
<string name="title_activity_discovery">Scanner les appareils</string>
<string name="initialized">Initialisé</string>
<string name="n_a">N.D.</string>
<string name="app_install_info">Vous êtes sur le point d\'installer l\'application suivante :
\n
\n
\n%1$s Version %2$s par %3$s
\n</string>
<string name="firmware_install_warning">VOUS TENTEZ D\'INSTALLER UN MICROLOGICIEL, PROCÉDEZ À VOS RISQUES ET PÉRILS.
\n
\n
\nCe micrologiciel est pour la version de matériel : %s</string>
<string name="installation_successful">Installé</string>
<string name="installation_failed_">Échec de l\'installation</string>
<string name="installing_binary_d_d">Installation du binaire %1$d/%2$d</string>
<string name="gadgetbridge_running">Gadgetbridge est en fonctionnement</string>
<string name="tap_a_device_to_connect">Tapez sur le périphérique pour le connecter</string>
<string name="tap_connected_device_for_vibration">Cliquez sur connecter pour envoyer une vibration</string>
<string name="tap_connected_device_for_activity">Cliquez sur l\'appareil pour ouvrir le gestionnaire dactivité</string>
<string name="tap_connected_device_for_app_mananger">Cliquez sur l\'appareil pour ouvrir le gestionnaire d\'application</string>
<string name="bluetooth_is_disabled_">Le Bluetooth est désactivé.</string>
<string name="bluetooth_is_not_supported_">Le Bluetooth n\'est pas supporté.</string>
<string name="this_is_a_test_notification_from_gadgetbridge">Ceci est un test de notification venant de Gadgetbridge</string>
<string name="test_notification">Notification de test</string>
<string name="test">Test</string>
<string name="_unknown_">(inconnu)</string>
<string name="unknown_state">État inconnu</string>
<string name="connected">Connecté</string>
<string name="connecting">Connexion en cours</string>
<string name="not_connected">Non connecté</string>
<string name="preferences_hplus_settings">Paramètres HPlus/Makibes</string>
<string name="prefs_title_all_day_heart_rate">Mesure de la fréquence cardiaque toute la journée</string>
<string name="pref_title_screentime">Durée d\'écran allumé</string>
<string name="pref_title_timeformat">Format de l\'heure</string>
<string name="pref_title_unit_system">Unités</string>
<string name="pref_title_pebble_reconnect_attempts">Tentatives de reconnexion</string>
<string name="pref_summary_pebble_always_ack_pebblekit">Ceci permettra aux messages envoyés à des apps tierces d\'être toujours reconnus immédiatement</string>
<string name="pref_title_pebble_always_ack_pebblekit">ACK à l\'avance du PebbleKit</string>
<string name="pref_summary_pebble_enable_applogs">Ceci permettra à Gadgetbridge de conserver les logs des Watch App (requiert une reconnexion)</string>
<string name="pref_title_pebble_enable_applogs">Activer les logs des apps du bracelet</string>
<string name="pref_summary_pebble_mtu_limit">Si votre Pebble 2/LE ne fonctionne pas correctement, essayez d\'activer cette option pour limiter le MTU (plage valide 20512)</string>
<string name="pref_title_pebble_mtu_limit">Limite du GATT MTU de Pebble 2/LE</string>
<string name="pref_summary_pebble_forcele">Utiliser le support expérimental du LE pour toutes les Pebble au lieu du Bluetooth classique. Cela requiert le jumelage d\'une Pebble non LE, puis d\'une Pebble LE</string>
<string name="pref_title_pebble_forcele">Toujours préférer le BLE</string>
<string name="pref_title_pebble_forceuntested">Activer les fonctionnalités non-testées</string>
<string name="pref_title_pebble_forceprotocol">Forcer le protocole de notification</string>
<string name="toast_aqurired_networklocation">Emplacement obtenu</string>
<string name="toast_enable_networklocationprovider">Veuillez activer la localisation réseau</string>
<string name="pref_title_location_keep_uptodate">Garder lemplacement à jour</string>
<string name="pref_title_location_longitude">Longitude</string>
<string name="pref_title_location_latitude">Latitude</string>
<string name="pref_title_location_aquire">Obtenir l\'emplacement</string>
<string name="pref_header_location">Emplacement</string>
<string name="pref_pebble_privacy_mode_complete">Ne montre que l\'icône de notification</string>
<string name="pref_pebble_privacy_mode_content">Déplace les notifications hors de l\'écran</string>
<string name="pref_pebble_privacy_mode_off">Notifications normales</string>
<string name="pref_title_pebble_privacy_mode">Mode privé</string>
<string name="pref_summary_autoremove_notifications">Les notifications sont automatiquement effacées de la Pebble lorsqu\'elles sont rejetées sur l\'appareil Android</string>
<string name="pref_title_autoremove_notifications">Effacer automatiquement les notifications rejetées</string>
<string name="pref_summary_enable_calendar_sync">Envoyer les événements du calendrier sur la timeline</string>
<string name="pref_title_enable_calendar_sync">Synchroniser le calendrier</string>
<string name="pref_summary_sunrise_sunset">Envoyer les heures de lever et coucher du soleil dans lhistorique Pebble en fonction de l\'emplacement</string>
<string name="pref_title_sunrise_sunset">Lever et coucher de soleil</string>
<string name="pref_header_pebble_timeline">Timeline Pebble</string>
<string name="pref_summary_enable_pebblekit">Activer le support expérimental pour les applications Android utilisant PebbleKit</string>
<string name="pref_title_enable_pebblekit">Permettre l\'accès aux applications tierces Android</string>
<string name="pref_summary_enable_outgoing_call">Désactiver ceci empêchera la Pebble 2/LE de vibrer lors des appels sortants</string>
<string name="pref_title_enable_outgoing_call">Support des appels sortants</string>
<string name="pref_title_pebble_sync_morpheuz">Synchroniser Morpheuz</string>
<string name="pref_title_pebble_sync_misfit">Synchroniser Misfit</string>
<string name="pref_title_pebble_sync_health">Synchroniser Pebble Health</string>
<string name="pref_title_pebble_activitytracker">Traqueur d\'activité préféré</string>
<string name="pref_header_activitytrackers">Traqueurs d\'activité</string>
<string name="pref_title_pebble_settings">Paramètres Pebble</string>
<string name="pref_title_development_miaddr">Adresse Mi Band</string>
<string name="pref_header_development">Options développeur</string>
<string name="pref_title_canned_messages_set">Mise à jour Pebble</string>
<string name="pref_title_canned_messages_dismisscall">Raccrocher</string>
<string name="pref_title_canned_reply_suffix">Suffixe fréquent</string>
<string name="pref_title_canned_replies">Réponses</string>
<string name="pref_header_cannned_messages">Modèles de messages</string>
<string name="pref_blacklist_calendars">Mettre des calendriers en liste noire</string>
<string name="pref_blacklist">Applications bloquées</string>
<string name="pref_call_privacy_mode_complete">Masquer le nom et le numéro</string>
<string name="pref_call_privacy_mode_number">Masquer le numéro mais afficher le nom</string>
<string name="pref_call_privacy_mode_name">Masquer le nom mais afficher le numéro</string>
<string name="pref_call_privacy_mode_off">Afficher le nom et le numéro</string>
<string name="pref_title_call_privacy_mode">Mode de confidentialité d\'appel</string>
<string name="pref_header_privacy">Confidentialité</string>
<string name="never">Jamais</string>
<string name="when_screen_off">Quand l\'écran est éteint</string>
<string name="always">Toujours</string>
<string name="pref_summary_transliteration">Activez ceci si votre appareil ne supporte pas la police de caractères</string>
<string name="pref_title_transliteration">Transcription</string>
<string name="pref_summary_notification_filter">Les notifications non-sollicitées sont suspendues dans ce mode</string>
<string name="pref_title_notification_filter">Ne Pas Déranger</string>
<string name="pref_title_whenscreenon">…y compris quand l\'écran est allumé</string>
<string name="pref_title_notifications_generic">Support des notifications génériques</string>
<string name="pref_summary_notifications_pebblemsg">Support des applications qui envoient des notification à Pebble via PebbleKit.</string>
<string name="pref_title_notifications_pebblemsg">Messages Pebble</string>
<string name="pref_title_notifications_sms">Textos</string>
<string name="pref_title_notifications_call">Appels téléphoniques</string>
<string name="pref_title_notifications_repetitions">Répétitions</string>
<string name="pref_header_notifications">Notifications</string>
<string name="pref_summary_minimize_priority_on">L\'icône de la barre d\'état et la notification de l\'écran de verrouillage sont masquées</string>
<string name="pref_summary_minimize_priority_off">L\'icône de la barre d\'état et la notification de l\'écran de verrouillage sont affichées</string>
<string name="pref_title_minimize_priority">Masquer la notification de Gadgetbridge</string>
<string name="pref_title_language">Langue</string>
<string name="pref_theme_dark">Sombre</string>
<string name="pref_theme_light">Clair</string>
<string name="pref_title_theme">Thème</string>
<string name="pref_summary_datetime_syctimeonconnect">Synchroniser l\'heure sur l\'appareil lors de la connexion, et lorsque l\'heure ou le fuseau horaire changent sur Android</string>
<string name="pref_title_datetime_syctimeonconnect">Synchroniser l\'heure</string>
<string name="pref_header_datetime">Date et heure</string>
<string name="pref_default">Par défaut</string>
<string name="pref_title_general_autostartonboot">Démarrer automatiquement</string>
<string name="pref_title_general_autoconnectonbluetooth">Connecter votre appareil quand le Bluetooth est activé</string>
<string name="pref_header_general">Paramètres généraux</string>
<string name="title_activity_settings">Paramètres</string>
<string name="miband_firmware_suggest_whitelist">Si vous désirez continuer malgré tout, et que tout fonctionne correctement par la suite, veuillez en informer les développeurs de Gadgetbridge pour demander l\'ajout du micrologiciel %s à leur liste blanche.</string>
<string name="miband_firmware_known">Ce micrologiciel a été testé et est connu pour être compatible avec Gadgetbridge.</string>
<string name="fw_multi_upgrade_notice">Vous êtes sur le point d\'installer les micrologiciels %1$s et %2$s à la place de ceux qui sont actuellement sur votre Mi Band.</string>
<string name="fw_upgrade_notice">Vous êtes sur le point d\'installer le micrologiciel %s.</string>
<string name="dbmanagementactivvity_cannot_access_export_path">Impossible d\'accéder au fichier d\'export. Merci de contacter les développeurs.</string>
<string name="activity_db_management_merge_old_title">Effacer l\'ancienne base de données</string>
<string name="activity_db_management_import_export_explanation">Les opérations sur la base de données ont utilisé le chemin suivant sur votre appareil.
\nCe chemin est accessible par d\'autres applications Android ou par votre ordinateur.
\nVotre base de données (ou celle que vous souhaitez importer) se trouvera ici :</string>
<string name="title_activity_db_management">Gestion de base de données</string>
<string name="action_db_management">Gestion de base de données</string>
<string name="pref_summary_pebble_health_store_raw">Si coché, les données « brutes » sont stockées pour une interprétation ultérieure, augmentant la taille de la base de données.</string>
<string name="title_activity_fw_app_insaller">Installateur d\'applications/firmware</string>
<string name="title_activity_calblacklist">Calendriers sur liste noire</string>
<string name="title_activity_appblacklist">Liste noire de notifications</string>
<string name="app_move_to_top">Haut de page</string>
<string name="app_configure">Configurer</string>
<string name="appmanager_weather_install_provider">Installer l\'application de notification de la météo</string>
<string name="appmanager_weather_deactivate">Désactiver l\'application météo</string>
<string name="appmanager_weather_activate">Activer l\'application météo</string>
<string name="appmanager_hrm_deactivate">Désactiver la mesure du rythme cardiaque</string>
<string name="appmanager_hrm_activate">Activer la mesure du rythme cardiaque</string>
<string name="appmanager_health_deactivate">Désactiver</string>
<string name="appmanager_health_activate">Activer</string>
<string name="appmanager_app_openinstore">Rechercher dans le magasin dapplication Pebble</string>
<string name="appmananger_app_reinstall">Réinstaller</string>
<string name="appmananger_app_delete_cache">Supprimer et effacer du cache</string>
<string name="appmananger_app_delete">Supprimer</string>
<string name="appmanager_installed_watchfaces">Watchfaces installées</string>
<string name="appmanager_installed_watchapps">Applis installées</string>
<string name="appmanager_cached_watchapps_watchfaces">Applis en cache</string>
<string name="title_activity_appmanager">Gestionnaire d\'application</string>
<string name="title_activity_debug">Déboguer</string>
<string name="controlcenter_snackbar_requested_screenshot">Capturer l\'écran de l\'appareil</string>
<string name="controlcenter_snackbar_connecting">Connexion…</string>
<string name="controlcenter_snackbar_disconnecting">Déconnexion</string>
<string name="controlcenter_snackbar_need_longpress">Presser longuement l\'icône pour déconnecter</string>
<string name="controlcenter_navigation_drawer_close">Fermer le tiroir de navigation</string>
<string name="controlcenter_navigation_drawer_open">Ouvrir le tiroir de navigation</string>
<string name="controlcenter_delete_device_name">Supprimer %1$s</string>
<string name="controlcenter_delete_device">Supprimer lappareil</string>
<string name="controlcenter_disconnect">Déconnecter</string>
<string name="controlcenter_take_screenshot">Prendre une capture d\'écran</string>
<string name="controlcenter_find_device">Retrouver votre appareil perdu</string>
<string name="controlcenter_fetch_activity_data">Synchroniser</string>
<string name="action_donate">Faire un don</string>
<string name="action_quit">Quitter</string>
<string name="action_debug">Déboguer</string>
<string name="action_settings">Paramètres</string>
</resources>

View File

@ -22,8 +22,8 @@
<string name="title_activity_debug">Déboguer</string>
<!--Strings related to AppManager-->
<string name="title_activity_appmanager">Gestionnaire d\'application</string>
<string name="appmanager_cached_watchapps_watchfaces">Apps en cache</string>
<string name="appmanager_installed_watchapps">Apps installées</string>
<string name="appmanager_cached_watchapps_watchfaces">Applis en cache</string>
<string name="appmanager_installed_watchapps">Applis installées</string>
<string name="appmanager_installed_watchfaces">Watchfaces installées</string>
<string name="appmananger_app_delete">Supprimer</string>
<string name="appmananger_app_delete_cache">Supprimer et effacer du cache</string>
@ -50,7 +50,7 @@
<string name="miband_firmware_unknown_warning">Ce micrologiciel n\'a pas été testé et peut ne pas être compatible avec Gadgetbridge.
\n
\nIl n\'est PAS conseillé de le flasher !</string>
<string name="miband_firmware_suggest_whitelist">Si vous désirez continuer et que tout fonctionne correctement par la suite, veuillez en informer les développeurs de Gadgetbridge pour demander l\'ajout du micrologiciel %s à leur liste.</string>
<string name="miband_firmware_suggest_whitelist">Si vous désirez continuer malgré tout, et que tout fonctionne correctement par la suite, veuillez en informer les développeurs de Gadgetbridge pour demander l\'ajout du micrologiciel %s à leur liste blanche.</string>
<!--Strings related to Settings-->
<string name="title_activity_settings">Paramètres</string>
<string name="pref_header_general">Paramètres généraux</string>
@ -129,9 +129,9 @@
<string name="toast_enable_networklocationprovider">Veuillez activer la localisation réseau</string>
<string name="toast_aqurired_networklocation">Emplacement obtenu</string>
<string name="pref_title_pebble_forceprotocol">Forcer le protocole de notification</string>
<string name="pref_summary_pebble_forceprotocol">Cette option force l\'utilisation du protocole de notification le plus récent selon votre version du micrologiciel. A VOS PROPRES RISQUES!</string>
<string name="pref_title_pebble_forceuntested">Activer les fonctionnalités non-testées</string>
<string name="pref_summary_pebble_forceuntested">Activer les fonctionnalités non-testées. A VOS PROPRES RISQUES !</string>
<string name="pref_summary_pebble_forceprotocol">Cette option force l\'utilisation du protocole de notification le plus récent selon votre version du micrologiciel. À VOS PROPRES RISQUES ET PÉRILS !</string>
<string name="pref_title_pebble_forceuntested">Activer les fonctionnalités non testées</string>
<string name="pref_summary_pebble_forceuntested">Activer les fonctionnalités non testées. À VOS PROPRES RISQUES ET PÉRILS !</string>
<string name="pref_title_pebble_forcele">Toujours préférer le BLE</string>
<string name="pref_summary_pebble_forcele">Utiliser le support expérimental du LE pour toutes les Pebble au lieu du Bluetooth classique. Cela requiert le jumelage d\'une Pebble non LE, puis d\'une Pebble LE</string>
<string name="pref_title_pebble_mtu_limit">Limite du GATT MTU de Pebble 2/LE</string>
@ -218,7 +218,7 @@
<string name="pref_screen_notification_profile_sms">Notification Texto</string>
<string name="pref_header_vibration_settings">Paramètres des vibrations</string>
<string name="pref_screen_notification_profile_generic">Notification générique</string>
<string name="pref_screen_notification_profile_email">Notification des mails</string>
<string name="pref_screen_notification_profile_email">Notification par courriel</string>
<string name="pref_screen_notification_profile_incoming_call">Notification d\'appels entrants</string>
<string name="pref_screen_notification_profile_generic_chat">Tchat</string>
<string name="pref_screen_notification_profile_generic_navigation">Navigation</string>
@ -265,7 +265,7 @@
<string name="fwapp_install_device_not_ready">Le fichier ne peut pas être installé, l\'appareil n\'est pas prêt.</string>
<string name="installhandler_firmware_name">%1$s: %2$s %3$s</string>
<string name="miband_fwinstaller_compatible_version">Version compatible</string>
<string name="miband_fwinstaller_untested_version">Version non-testée !</string>
<string name="miband_fwinstaller_untested_version">Version non testée !</string>
<string name="fwappinstaller_connection_state">Connexion à l\'appareil : %1$s</string>
<string name="pbw_installhandler_pebble_firmware">Micrologiciel Pebble %1$s</string>
<string name="pbwinstallhandler_correct_hw_revision">Version du matériel correcte</string>
@ -327,7 +327,7 @@
<string name="waiting_for_reconnect">En attente de reconnexion</string>
<string name="activity_prefs_about_you">À propos de vous</string>
<string name="activity_prefs_year_birth">Année de naissance</string>
<string name="activity_prefs_gender">Genre</string>
<string name="activity_prefs_gender">Sexe</string>
<string name="activity_prefs_height_cm">Taille en cm</string>
<string name="activity_prefs_weight_kg">Poids en kg</string>
<string name="authenticating">Authentification</string>
@ -346,7 +346,7 @@ Temps de sommeil préféré en heures</string>
<string name="charts_legend_heartrate">Fréquence cardiaque</string>
<string name="live_activity_heart_rate">Fréquence cardiaque</string>
<string name="pref_title_pebble_health_store_raw">Stockez les enregistrements brut dans la base de données</string>
<string name="pref_summary_pebble_health_store_raw">Si coché, les données \"brutes\" sont stockées pour une interprétation ultérieure, augmentant la taille de la base de données.</string>
<string name="pref_summary_pebble_health_store_raw">Si coché, les données « brutes » sont stockées pour une interprétation ultérieure, augmentant la taille de la base de données.</string>
<string name="action_db_management">Gestion de base de données</string>
<string name="title_activity_db_management">Gestion de base de données</string>
<string name="activity_db_management_import_export_explanation">Les opérations sur la base de données ont utilisé le chemin suivant sur votre appareil.
@ -407,17 +407,17 @@ Temps de sommeil préféré en heures</string>
<string name="discovery_dont_pair">Ne pas appairer</string>
<string name="fw_upgrade_notice_amazfitbip">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Bip.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res, puis le fichier.gps. Votre montre redémarrera après installation du .fw.
\nVeuillez installer le fichier .fw, puis le fichier .res, puis le fichier.gps.. Votre montre redémarrera après installation du .fw.
\n
\nNote : vous ne devez pas installer .res et .gps si ceux-ci sont identiques à ceux installés précédemment.
\nNote : vous ne devez pas installer les fichiers .res et .gps si ceux-ci sont identiques à ceux installés précédemment.
\n
\nCONTINUEZ À VOS RISQUES !</string>
\nCONTINUEZ À VOS RISQUES ET PÉRILS !</string>
<string name="mi2_prefs_button_actions">Actions du bouton</string>
<string name="mi2_prefs_button_actions_summary">Spécifier les actions par pression du bouton</string>
<string name="mi2_prefs_button_press_count">Nombre de pressions du bouton</string>
<string name="mi2_prefs_button_press_count_summary">Nombre d\'appuis sur le boutton pour envoyer lÉvènement 1. Appuyer de nouveau autant de fois créera l\'Évènement 2, etc.</string>
<string name="mi2_prefs_button_press_broadcast">Message à envoyer</string>
<string name="mi2_prefs_button_press_broadcast_summary">Message de diffusion envoyé avec l\'évènement. Le paramètre `button_id` est automatiquement ajouté à chaque message.</string>
<string name="mi2_prefs_button_press_broadcast_summary">Message de diffusion envoyé avec l\'évènement. Le paramètre « button_id » est automatiquement ajouté à chaque message.</string>
<string name="mi2_prefs_button_action">Activer action du bouton</string>
<string name="mi2_prefs_button_action_summary">Activer action après nombre spécifié de pressions</string>
<string name="mi2_prefs_button_action_vibrate">Activer la vibration du bracelet</string>
@ -433,13 +433,13 @@ Temps de sommeil préféré en heures</string>
<string name="pref_summary_pebble_enable_bgjs">Si activé, autorise l\'affichage de la météo, niveau de batterie, etc.</string>
<string name="activity_web_view">Activité Web View</string>
<string name="controlcenter_connect">Connexion…</string>
<string name="fw_upgrade_notice_amazfitcor">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : Il n\'est pas nécessaire d\'installer le fichier .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES !</string>
<string name="fw_upgrade_notice_amazfitcor">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du .fw.
\n
\nNote : vous ne devez pas installer .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES ET PÉRILS !</string>
<string name="pref_title_charts_swipe">Permettre le balayage gauche/droite dans les graphiques d\'activité</string>
<string name="automatic">Automatique</string>
<string name="simplified_chinese">Chinois simplifié</string>
@ -512,15 +512,15 @@ Temps de sommeil préféré en heures</string>
<string name="menuitem_alipay">Alipay</string>
<string name="blacklist_all_for_notifications">Mettre toutes les notifications en liste noire</string>
<string name="whitelist_all_for_notifications">Mettre toutes les notifications en liste blanche</string>
<string name="fw_upgrade_notice_miband3">Vous allez installer le micrologiciel %s dans votre Mi Band 3.
\n
\nAssurez-vous d\'installer d\'abord le fichier .fw, et ensuite le fichiers .res. Votre bracelet redémarrera après l\'installation du fichiers .fw.
\n
\nRemarque : Vous n\'avez pas besoin d\'installer le fichier .res si c\'est exactement le même que celui déjà installé.
\n
\nÀ VOS RISQUES ET PÉRILS !</string>
<string name="fw_upgrade_notice_miband3">Vous allez installer le micrologiciel %s dans votre Mi Band 3.
\n
\nAssurez-vous d\'installer d\'abord le fichier .fw, et ensuite le fichiers .res. Votre bracelet redémarrera après l\'installation du fichiers .fw.
\n
\nRemarque : Vous n\'avez pas besoin d\'installer le fichier .res si c\'est exactement le même que celui déjà installé.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS !</string>
<string name="pref_title_pebble_gatt_clientonly">client GATT uniquement</string>
<string name="pref_summary_pebble_gatt_clientonly">C\'est uniquement pour les Pebble 2 et expérimental, à essayer si vous avez des problèmes de connectivité</string>
<string name="pref_summary_pebble_gatt_clientonly">Pour Pebble 2 seulement et expérimental, essayez seulement si vous avez des problèmes de connexion</string>
<string name="prefs_screen_orientation">Orientation de l\'écran</string>
<string name="pref_auto_fetch">Récupérer automatiquement les données d\'activité</string>
<string name="pref_auto_fetch_summary">Récupération au déverrouillage de l\'écran. Fonctionne uniquement si un mécanisme de verrouillage est configuré !</string>
@ -538,7 +538,7 @@ Temps de sommeil préféré en heures</string>
<string name="menuitem_notifications">Notifications</string>
<string name="menuitem_music">Musique</string>
<string name="menuitem_more">Suite</string>
<string name="controlcenter_change_led_color">Changer la couleur de la LED</string>
<string name="controlcenter_change_led_color">Changer la couleur de la DEL</string>
<string name="controlcenter_change_fm_frequency">Changer la fréquence FM</string>
<string name="controlcenter_calibrate_device">Calibrer l\'appareil</string>
<string name="pref_title_notifications_timeout">Durée minimum entre deux notifications</string>
@ -546,10 +546,10 @@ Temps de sommeil préféré en heures</string>
<string name="pref_summary_rtl">Cocher ceci si votre appareil n\'est pas compatible avec les langues \"droite-à-gauche\"</string>
<string name="pref_rtl_max_line_length">Longueur max. d\'une ligne en mode Droite-à-Gauche</string>
<string name="watch9_pairing_tap_hint">Lorsque votre bracelet vibre, secouez-le ou pressez son bouton.</string>
<string name="notif_battery_low">%1$s niveau de batterie bas</string>
<string name="notif_battery_low_extended">%1$s niveau de batterie base : %2$s</string>
<string name="lack_of_sleep">Manque de sommeil: %1$s</string>
<string name="overslept">Excès de sommeil: %1$s</string>
<string name="notif_battery_low">%1$s batterie faible</string>
<string name="notif_battery_low_extended">%1$s batterie faible : %2$s</string>
<string name="lack_of_sleep">Manque de sommeil : %1$s</string>
<string name="overslept">Excès de sommeil : %1$s</string>
<string name="no_limit">Sans limite</string>
<string name="seconds_5">5 secondes</string>
<string name="seconds_10">10 secondes</string>
@ -559,9 +559,9 @@ Temps de sommeil préféré en heures</string>
<string name="minutes_5">5 minutes</string>
<string name="minutes_10">10 minutes</string>
<string name="minutes_30">30 minutes</string>
<string name="lack_of_step">Manque d\'activité: %1$d</string>
<string name="overstep">Trop d\'activité: %1$d</string>
<string name="live_activity_max_heart_rate">Mesure cardiaque actuelle / maximum: %1$d / %2$d</string>
<string name="lack_of_step">Manque d\'activité : %1$d</string>
<string name="overstep">Trop d\'activité : %1$d</string>
<string name="live_activity_max_heart_rate">Mesure cardiaque actuelle / maximum : %1$d / %2$d</string>
<string name="you_slept">Vous avez dormi de %1$s à %2$s</string>
<string name="you_did_not_sleep">Vous n\'avez pas dormi</string>
<string name="mi3_prefs_band_screen_unlock_summary">Glisser le doigt vers le haut pour débloquer l\'écran du bracelet</string>
@ -579,9 +579,9 @@ Temps de sommeil préféré en heures</string>
<string name="ok">Ok</string>
<string name="mi3_night_mode_sunset">Au coucher du soleil</string>
<string name="devicetype_watch9">Watch 9</string>
<string name="watch9_time_minutes">Minutes:</string>
<string name="watch9_time_hours">Heures:</string>
<string name="watch9_time_seconds">Secondes:</string>
<string name="watch9_time_minutes">Minutes :</string>
<string name="watch9_time_hours">Heures :</string>
<string name="watch9_time_seconds">Secondes :</string>
<string name="watch9_calibration_hint">Régler l\'heure que votre appareil indique actuellement.</string>
<string name="watch9_calibration_button">Calibrer</string>
<string name="title_activity_watch9_pairing">Appairage de la Watch 9</string>
@ -589,9 +589,9 @@ Temps de sommeil préféré en heures</string>
<string name="preferences_rtl_settings">Support Droite-à-Gauche</string>
<string name="share_log">Partager les logs</string>
<string name="share_log_warning">Veuillez garder à l\'esprit que les fichiers logs de Gadgetbridge peuvent contenir des tas d\'informations personnelles, incluant entre autre des données relatives à la santé, des identifiants uniques (telles que des adresses MAC), des préférences musicales, etc. Pensez à modifier le fichier et retirer ces informations personnelles avant toute publication sur un rapport de bug public.</string>
<string name="warning">Attention!</string>
<string name="warning">Attention !</string>
<string name="no_data">Pas de données</string>
<string name="preferences_led_color">Couleur de la LED</string>
<string name="preferences_led_color">Couleur de la DEL</string>
<string name="preferences_fm_frequency">Fréquence FM</string>
<string name="pref_invalid_frequency_title">Fréquence non-valide</string>
<string name="pref_invalid_frequency_message">Veuillez introduire une fréquence entre 87.5 et 108.0</string>
@ -601,7 +601,7 @@ Temps de sommeil préféré en heures</string>
<string name="devicetype_roidmi3">Roidmi 3</string>
<string name="pref_title_contextual_arabic">Arabe contextuel</string>
<string name="pref_summary_contextual_arabic">A cocher pour activer le support \"Arabe contextuel\"</string>
<string name="debugactivity_really_factoryreset_title">Confirmer la réinitialisation \?</string>
<string name="debugactivity_really_factoryreset_title">Vraiment retourner aux paramètres d\'usine \?</string>
<string name="debugactivity_really_factoryreset">Une réinitialisation effacera toutes les données de l\'appareil connecté (si supporté). Les appareils Xiaomi/Huami modifient également l\'adresse MAC Bluetooth, de sorte qu\'ils apparaissent comme de nouveaux appareils dans Gadgetbridge.</string>
<string name="mi3_prefs_band_screen_unlock">Déverrouillage de l\'écran du Band</string>
<string name="activity_type_exercise">Activité physique</string>
@ -619,7 +619,7 @@ Temps de sommeil préféré en heures</string>
<string name="filter_mode">Mode Filtre</string>
<string name="mode_configuration">Mode Configuration</string>
<string name="save_configuration">Sauvegarder la configuration</string>
<string name="appwidget_not_connected">Non connecté, lalarme nest pas définie.</string>
<string name="appwidget_not_connected">Non connecté, l\'alarme n\'est pas définie.</string>
<string name="prefs_disconnect_notification">Notification de déconnexion</string>
<string name="zetime_title_settings">Paramètres ZeTime</string>
<string name="zetime_title_heartrate">Paramètres Fréquence Cardiaque</string>
@ -633,7 +633,7 @@ Temps de sommeil préféré en heures</string>
<string name="zetime_analog_mode_hands">Aiguilles seulement</string>
<string name="zetime_analog_mode_handsandsteps">Aiguilles et Pas</string>
<string name="zetime_activity_tracking">Suivi des Activités</string>
<string name="zetime_activity_tracking_summary">"Activer le suivi des activités : comptera vos pas, etc."</string>
<string name="zetime_activity_tracking_summary">Activer le suivi des activités : comptera vos pas, etc.</string>
<string name="zetime_handmove_display_summary">Tourner le poignet pour activer ou désactiver l\'écran.</string>
<string name="zetime_calories_type">Type de calories</string>
<string name="zetime_calories_type_active">Seulement les calories brûlées activement</string>
@ -667,23 +667,23 @@ Temps de sommeil préféré en heures</string>
<string name="pref_screen_notification_profile_anti_loss">Alerte Anti-Perte</string>
<string name="interval_fifteen_minutes">Toutes les 15 min</string>
<string name="interval_forty_five_minutes">Toutes les 45 min</string>
<string name="activity_prefs_calories_burnt">Objectif Quotidien : Calories Brulées</string>
<string name="activity_prefs_distance_meters">Objectif Quotidien : Distance en mètres</string>
<string name="activity_prefs_activetime_minutes">Objectif Quotidien : Temps d\'activité en minutes</string>
<string name="activity_prefs_calories_burnt">Objectif quotidien : calories brulées</string>
<string name="activity_prefs_distance_meters">Objectif quotidien : distance en mètres</string>
<string name="activity_prefs_activetime_minutes">Objectif quotidien : temps d\'activité en minutes</string>
<string name="devicetype_miscale2">Mi Scale 2</string>
<string name="pref_title_support_voip_calls">Activer les applications d\'appel VoIP</string>
<string name="title_activity_device_specific_settings">Paramètres spécifiques de l\'appareil</string>
<string name="pref_title_authkey">Clé Auteur</string>
<string name="pref_summary_authkey">Changez la clé auteur à une clé générale sur tous vos appareils Android sur lesquels vous souhaitez vous connecter. La précédente clé par défaut était 0123456789@ABCDE</string>
<string name="devicetype_bfh16">BFH-16</string>
<string name="fw_upgrade_notice_amazfitcor2">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor 2.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du .fw.
\n
\nNote : il n\'est pas nécessaire d\'installer le fichier .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES !
\n
<string name="fw_upgrade_notice_amazfitcor2">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit Cor 2.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res. Votre montre redémarrera après installation du .fw.
\n
\nNote : il n\'est pas nécessaire d\'installer le fichier .res si celui-ci est identique à celui installé précédemment.
\n
\nCONTINUEZ À VOS RISQUES ET PÉRILS !
\n
\nNON TESTÉ, IL PEUT ÊTRE NÉCESSAIRE DE FLASHER UN MICROLOGICIEL BEATS_W SI LE NOM DE L\'APPAREIL EST « Amazfit Band 2 »</string>
<string name="dutch">Néerlandais</string>
<string name="turkish">Turc</string>
@ -697,13 +697,13 @@ Temps de sommeil préféré en heures</string>
<string name="pref_rtl_max_line_length_summary">Allonge ou raccourcis les lignes dans les textes écrits de droite à gauche</string>
<string name="zetime_handmove_display">Mouvement de la main</string>
<string name="devicetype_miband4">Mi Band 4</string>
<string name="fw_upgrade_notice_miband4">Vous êtes sur le point d\'installer le firmware %s sur votre Mi Band 4.
\n
\nVeuillez vous assurez d\'installer le fichier .fw, et après que le fichier .res. Votre bracelet redémarrera après l\'installation du fichier .fw.
\n
\nRemarque : Vous n\'avez pas à installer .res s\'il est exactement le même que celui précédemment installé.
\n
\nÀ VOS RISQUES ET PÉRILS !</string>
<string name="fw_upgrade_notice_miband4">Vous êtes sur le point d\'installer le firmware %s sur votre Mi Band 4.
\n
\nVeuillez vous assurez d\'installer le fichier .fw, et après que le fichier .res. Votre bracelet redémarrera après l\'installation du fichier .fw.
\n
\nRemarque : Vous n\'avez pas à installer .res s\'il est exactement le même que celui précédemment installé.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS !</string>
<string name="prefs_hr_alarm_activity">Alarme de la fréquence cardiaque durant une activité sportive</string>
<string name="prefs_hr_alarm_low">Limite basse</string>
<string name="prefs_hr_alarm_high">Limite haute</string>
@ -715,11 +715,11 @@ Temps de sommeil préféré en heures</string>
<string name="weeksleepchart_sleep_a_month">Sommeil par mois</string>
<string name="menuitem_nfc">NFC</string>
<string name="pref_title_use_custom_font">Utiliser une police personnalisée</string>
<string name="activity_DB_test_export_message">Exportation de la base de données </string>
<string name="activity_DB_test_export_message">Exportation de la base de données…</string>
<string name="activity_db_management_exportimport_label">Exporter et Importer</string>
<string name="widget_steps_label">Pas : %1$02d</string>
<string name="widget_listing_label">État et alarmes</string>
<string name="widget_set_alarm_after">Régler lalarme après :</string>
<string name="widget_listing_label">Statuts et Alarmes</string>
<string name="widget_set_alarm_after">Définir l\'alarme après :</string>
<string name="widget_5_minutes">5 minutes</string>
<string name="widget_10_minutes">10 minutes</string>
<string name="widget_20_minutes">20 minutes</string>
@ -728,21 +728,21 @@ Temps de sommeil préféré en heures</string>
<string name="pref_display_add_device_fab_off">Visible uniquement si aucun appareil n\'est ajouté</string>
<string name="prefs_find_phone_duration">Durée de la sonnerie en secondes</string>
<string name="maximum_duration">Durée</string>
<string name="pref_charts_range_on">La portée des graphs est réglée sur un mois</string>
<string name="pref_charts_range_off">La portée des graphs est réglée sur une semaine</string>
<string name="pref_charts_range_on">Gamme des graphiques positionnée sur un mois</string>
<string name="pref_charts_range_off">Gamme des graphiques positionnée sur une semaine</string>
<string name="devicetype_mijia_lywsd02">Mijia Smart Clock</string>
<string name="pref_summary_expose_hr">Permettre aux autres applis d\'accéder aux données de fréquence cardiaque en temps réel lorsque Gadgetbridge est connecté</string>
<string name="pref_title_expose_hr">Accès tiers fréq. cardiaque</string>
<string name="pref_summary_use_custom_font">À activer si votre appareil a une police spéciale embarquée pour prendre en charge les émoticônes</string>
<string name="pref_summary_use_custom_font">Activer ceci afin dafficher les émojis si votre appareil a un micrologiciel de police personnalisée</string>
<string name="activity_db_management_autoexport_explanation">L\'export automatique des données est réglé vers :</string>
<string name="activity_db_management_autoexport_label">Export auto</string>
<string name="activity_DB_ExportButton">Export de données</string>
<string name="activity_DB_import_button">Import de données</string>
<string name="activity_DB_test_export_button">Lancer l\'export maintenant</string>
<string name="activity_DB_delete_legacy_button">Supprimer les anciennes données</string>
<string name="activity_db_management_autoexport_label">Exportation automatique</string>
<string name="activity_DB_ExportButton">Exporter la base de données</string>
<string name="activity_DB_import_button">Importer la base de données</string>
<string name="activity_DB_test_export_button">Lancer immédiatement l\'exportation automatique</string>
<string name="activity_DB_delete_legacy_button">Supprimer l\'ancienne base de données</string>
<string name="activity_DB_empty_button">Vider la base de données</string>
<string name="activity_db_management_empty_DB">Vider la base de données</string>
<string name="activity_db_management_empty_db_warning">Attention ! Ce bouton détruit votre base de données et réinitialise.</string>
<string name="activity_db_management_empty_db_warning">Attention ! En cliquant sur ce bouton, vous supprimerez toutes vos données et recommencerez à zéro.</string>
<string name="appwidget_sleep_alarm_widget_label">Réveil</string>
<string name="widget_sleep_label">Sommeil : %1$s</string>
<plurals name="widget_alarm_target_hours">
@ -770,23 +770,23 @@ Temps de sommeil préféré en heures</string>
\n
\nÀ VOS RISQUES ET PÉRILS !</string>
<string name="devicetype_amazfit_gtr">Amazfit GTR</string>
<string name="fw_upgrade_notice_amazfitgtr">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTR.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS !</string>
<string name="fw_upgrade_notice_amazfitgtr">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTR.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS !</string>
<string name="pref_title_chart_heartrate_color">Couleur du rythme cardiaque</string>
<string name="pref_title_chart_sleep_rolling_24_hour">Plage de sommeil</string>
<string name="devicetype_amazfit_gts">Amazfit GTS</string>
<string name="fw_upgrade_notice_amazfitgts">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTS.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS !</string>
<string name="fw_upgrade_notice_amazfitgts">Vous êtes sur le point d\'installer le micrologiciel %s sur votre Amazfit GTS.
\n
\nVeuillez installer le fichier .fw, puis le fichier .res et enfin le fichier .gps. Votre montre redémarrera après installation du fichier .fw.
\n
\nNote : vous n\'avez pas à installer les fichiers .res et .gps s\'ils sont exactement les mêmes que ceux installés précédemment.
\n
\nÀ VOS RISQUES ET PÉRILS ET PÉRILS !</string>
<string name="devicetype_qhybrid">Fossil Q Hybrid</string>
<string name="preferences_qhybrid_settings">Paramètres hybrides Q</string>
<string name="watch_not_connected">Montre non connectée</string>
@ -829,4 +829,21 @@ Temps de sommeil préféré en heures</string>
<string name="find_lost_device_you_found_it">Trouvé !</string>
<string name="pref_title_force_white_color_scheme">Forcer le noir sur le blanc</string>
<string name="pref_summary_force_white_color_scheme">Utile si votre montre a les mains noires</string>
<string name="pref_title_lower_button_function">Bouton inférieur</string>
<string name="pref_title_middle_button_function">Bouton du milieu</string>
<string name="pref_title_upper_button_function">Bouton supérieur</string>
<string name="hr_appname_commute">Trajet</string>
<string name="hr_appname_stopwatch">Chronomètre</string>
<string name="hr_appname_workout">Entraînement</string>
<string name="hr_appname_wellness">Bien-être</string>
<string name="notification_channel_high_priority_name">Priorité haute des notifications Gadgetbridge</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="find_my_phone_notification">Trouver mon téléphone</string>
<string name="pref_title_vibration_strength">Puissance du vibreur</string>
<string name="pref_title_relax_firmware_checks">Activez cette option si vous souhaitez flasher un microprogramme qui n\'est pas destiné à votre appareil (à vos propres risques)</string>
<string name="pref_summary_relax_firmware_checks">Assouplir les contrôles des microprogrammes</string>
<string name="pref_summary_custom_deviceicon">Afficher une icône de notification Android spécifique à l\'appareil à la place de l\'icône Gadgetbridge lors de la connexion</string>
<string name="pref_title_custom_deviceicon">Afficher licône de notification spécifique à lappareil</string>
<string name="pref_qhybrid_title_widget_draw_circles">Widget traçant des cercles</string>
<string name="pref_header_auto_fetch">Récupération automatique</string>
</resources>

View File

@ -849,4 +849,10 @@
<string name="pref_title_upper_button_function">כפתור עליון</string>
<string name="pref_title_middle_button_function">כפתור אמצעי</string>
<string name="pref_title_lower_button_function">כפתור תחתון</string>
<string name="pref_title_vibration_strength">עצמת הרטט</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_relax_firmware_checks">יש להפעיל זאת אם מטרתך היא לצרוב קושחה שאינה מיועדת להתקן שלך (באחריותך הבלעדית)</string>
<string name="pref_summary_relax_firmware_checks">הפחתת בדיקות חומרה</string>
<string name="pref_header_auto_fetch">קבלה אוטומטית</string>
<string name="pref_qhybrid_title_widget_draw_circles">ציור עיגולי וידג׳טים</string>
</resources>

View File

@ -383,7 +383,7 @@
<string name="find_device_you_found_it">Trovato!</string>
<string name="find_lost_device_you_found_it">Trovato!</string>
<string name="miband2_prefs_timeformat">Mi2: Formato dell\'orario</string>
<string name="mi2_fw_installhandler_fw53_hint">E\' necessario installare la verione %1$s prima di installare questo firmware!</string>
<string name="mi2_fw_installhandler_fw53_hint">È necessario installare la verione %1$s prima di installare questo firmware!</string>
<string name="mi2_enable_text_notifications">Notifiche</string>
<string name="mi2_enable_text_notifications_summary">Richiede firmware versione minima 1.9.1.28 e Mili_pro.ft* installati.</string>
<string name="off">spento</string>
@ -826,4 +826,19 @@
<string name="qhybrid_second_timezone_offset_relative_to_utc">compensazione del secondo fuso orario rispetto a UTC</string>
<string name="qhybrid_offset_timezone">compensazione del fuso orario di</string>
<string name="qhybrid_offset_time_by">compensazione dell\'ora di</string>
<string name="pref_title_lower_button_function">Pulsante inferiore</string>
<string name="pref_title_middle_button_function">Pulsante centrale</string>
<string name="pref_title_upper_button_function">Pulsante superiore</string>
<string name="hr_appname_commute">Commute</string>
<string name="hr_appname_stopwatch">Cronometro</string>
<string name="hr_appname_workout">Allenamento</string>
<string name="hr_appname_wellness">Benessere</string>
<string name="qhybrid_use_activity_hand_as_notification_counter">utilizzare la mano di attività come contatore di notifica</string>
<string name="qhybrid_overwrite_buttons">sovrascrivere i pulsanti</string>
<string name="notification_channel_high_priority_name">Notifiche di Gadgetbridge ad alta priorità</string>
<string name="find_my_phone_notification">Trova il mio telefono</string>
<string name="pref_title_vibration_strength">Resistenza alle vibrazioni</string>
<string name="pref_title_relax_firmware_checks">Attivare questo se si vuole far lampeggiare un firmware non destinato al proprio dispositivo (a proprio rischio e pericolo)</string>
<string name="pref_summary_custom_deviceicon">Mostra l\'icona di notifica di un dispositivo specifico per Android invece l\'icona di Gadgetbridge quando è connesso</string>
<string name="pref_title_custom_deviceicon">Mostra l\'icona di notifica specifica del dispositivo</string>
</resources>

View File

@ -836,4 +836,24 @@
<string name="hr_widget_battery">Batteri</string>
<string name="hr_widget_weather">Vær</string>
<string name="hr_widget_nothing">Ingenting</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="hr_appname_wellness">Velvære</string>
<string name="hr_appname_workout">Treningsøkt</string>
<string name="pref_title_custom_deviceicon">Vis enhetsspesifikt merknadsikon</string>
<string name="hr_appname_stopwatch">Stoppeklokke</string>
<string name="pref_title_lower_button_function">Nedre knapp</string>
<string name="pref_title_middle_button_function">Midtknapp</string>
<string name="pref_title_upper_button_function">Øvre knapp</string>
<string name="find_lost_device_you_found_it">Fant den!</string>
<string name="pref_title_vibration_strength">Vibrasjonsstyrke</string>
<string name="hr_appname_commute">Pendle</string>
<string name="notification_channel_high_priority_name">Gadgetbridge-varsler har høy prioritet</string>
<string name="pref_summary_force_white_color_scheme">Nyttig hvis klokken din har mørke hender</string>
<string name="pref_title_force_white_color_scheme">Tving svart på hvitt fargevalg</string>
<string name="find_my_phone_notification">Finn min telefon</string>
<string name="pref_title_relax_firmware_checks">Aktiver dette hvis du vil blinke en fastvare som ikke er beregnet på enheten din (på egen risiko)</string>
<string name="pref_summary_relax_firmware_checks">Slapp av firmwarekontroller</string>
<string name="pref_summary_custom_deviceicon">Vis et enhetsspesifikt Android-varslingsikon i stedet for Gadgetbridge-ikonet når du er tilkoblet</string>
<string name="pref_qhybrid_title_widget_draw_circles">Tegn miniprogramssirkler</string>
<string name="pref_header_auto_fetch">Hent automatisk</string>
</resources>

View File

@ -847,4 +847,10 @@
<string name="pref_title_upper_button_function">Bovenste knop</string>
<string name="pref_title_middle_button_function">Middelste knop</string>
<string name="pref_title_lower_button_function">Onderste knop</string>
<string name="pref_title_vibration_strength">Trillingssterkte</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_relax_firmware_checks">Schakel dit in als u een firmware wilt flashen die niet voor uw apparaat bedoeld is (op eigen risico)</string>
<string name="pref_summary_relax_firmware_checks">Ontspannen firmwarecontroles</string>
<string name="pref_header_auto_fetch">Automatisch ophalen</string>
<string name="pref_qhybrid_title_widget_draw_circles">Teken widget cirkels</string>
</resources>

View File

@ -836,4 +836,20 @@
<string name="hr_widget_weather">Pogoda</string>
<string name="hr_widget_nothing">Nic</string>
<string name="find_lost_device_you_found_it">Odnaleziono!</string>
<string name="find_my_phone_notification">Znajdź mój telefon</string>
<string name="pref_title_custom_deviceicon">Pokaż specyficzną dla urządzenia ikonę powiadomienia</string>
<string name="hr_widget_active_minutes">Minuty aktywności</string>
<string name="pref_title_force_white_color_scheme">Wymuś schemat kolorów czarno na białym</string>
<string name="pref_summary_force_white_color_scheme">Użyteczne, jeśli twój zegarek ma ciemne wskazówki</string>
<string name="notification_channel_high_priority_name">Powiadomienia Gadgetbridge o wysokim priorytecie</string>
<string name="pref_summary_custom_deviceicon">Pokaż specyficzną dla urządzenia ikonę powiadomienia zamiast ikony Gadgetbridge, gdy połączono</string>
<string name="hr_appname_workout">Trening</string>
<string name="hr_appname_stopwatch">Stoper</string>
<string name="pref_title_upper_button_function">Górny przycisk</string>
<string name="pref_title_middle_button_function">Środkowy przycisk</string>
<string name="pref_title_lower_button_function">Dolny przycisk</string>
<string name="pref_title_vibration_strength">Siła wibracji</string>
<string name="devicetype_amazfit_bips"></string>
<string name="pref_title_relax_firmware_checks">Włącz to, jeśli chcesz błyskać oprogramowaniem sprzętowym, które nie jest przeznaczone dla Twojego urządzenia (na własne ryzyko)</string>
<string name="pref_summary_relax_firmware_checks">Zrelaksuj kontrolę oprogramowania sprzętowego</string>
</resources>

View File

@ -859,4 +859,10 @@
<string name="pref_title_upper_button_function">Botão superior</string>
<string name="pref_title_middle_button_function">Botão do meio</string>
<string name="pref_title_lower_button_function">Botão inferior</string>
<string name="pref_title_vibration_strength">Intensidade da vibração</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="pref_title_relax_firmware_checks">Habilite isso se você deseja instalar um firmware não destinado para seu dispositivo (a seu próprio risco)</string>
<string name="pref_summary_relax_firmware_checks">Verificações de firmware relaxadas</string>
<string name="pref_header_auto_fetch">Coletar automaticamente</string>
<string name="pref_qhybrid_title_widget_draw_circles">Desenhar círculos de widget</string>
</resources>

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,7 @@
<string name="pref_title_canned_replies">Відповіді</string>
<string name="pref_title_canned_reply_suffix">Загальний суфікс</string>
<string name="pref_header_development">Параметри для розробників</string>
<string name="pref_title_development_miaddr">Адреса Mi Band</string>
<string name="pref_title_development_miaddr">Адреса Mi-Band</string>
<string name="pref_title_pebble_settings">Параметри Pebble</string>
<string name="pref_header_activitytrackers">Трекер активності</string>
<string name="pref_title_pebble_activitytracker">Бажаний трекер активності</string>
@ -117,7 +117,7 @@
<string name="title_activity_mi_band_pairing">Створення пари з Вашим Mi Band</string>
<string name="message_cannot_pair_no_mac">Немає MAC-адресу, не вдалося створити пару.</string>
<string name="preferences_category_device_specific_settings">Параметри специфічні для пристрою</string>
<string name="preferences_miband_settings">Параметри MiBand / Amazfit</string>
<string name="preferences_miband_settings">Параметри Mi-Band / Amazfit</string>
<string name="male">Чоловіча</string>
<string name="female">Жіноча</string>
<string name="other">Інше</string>
@ -145,9 +145,9 @@
<string name="vibration_profile_alarm_clock">Будильник</string>
<string name="miband_prefs_vibration">Вібрація</string>
<string name="pref_screen_notification_profile_sms">SMS-сповіщення</string>
<string name="pref_header_vibration_settings">Параметри вібровідгуку</string>
<string name="pref_header_vibration_settings">Параметри вібрації</string>
<string name="pref_screen_notification_profile_generic">Загальні сповіщення</string>
<string name="pref_screen_notification_profile_incoming_call">Сповіщення під час вхідного дзвінку</string>
<string name="pref_screen_notification_profile_incoming_call">Сповіщення вхідного дзвінка</string>
<string name="pref_screen_notification_profile_generic_chat">Чат</string>
<string name="pref_screen_notification_profile_generic_navigation">Навігація</string>
<string name="pref_screen_notification_profile_generic_social">Соціальні мережі</string>
@ -204,7 +204,7 @@
<string name="weeksteps_today_steps_description">Кроків сьогодні, мета: %1$s</string>
<string name="pref_title_dont_ack_transfer">Не передавати дані про активність</string>
<string name="pref_summary_dont_ack_transfers">Якщо дані не будуть передані на пристрій, пристрій не буде очищений. Корисно, якщо Gadgetbridge використовується разом з іншими додатками.</string>
<string name="pref_summary_keep_data_on_device">Дозволяє лишити дані на Mi-браслеті після синхронізації. Зазвичай використовується, якщо GB працює ще з іншими додатками.</string>
<string name="pref_summary_keep_data_on_device">Дозволяє залишити дані на Mi-Band після синхронізації. Зазвичай використовується, якщо GB працює разом з іншими додатками.</string>
<string name="live_activity_steps_history">Історія кроків</string>
<string name="live_activity_current_steps_per_minute">Поточні кроки/хв</string>
<string name="live_activity_total_steps">Загалом кроків</string>

View File

@ -41,19 +41,19 @@
<string name="title_activity_calblacklist">阻止记录</string>
<string name="title_activity_fw_app_insaller">FW/App 安装器</string>
<string name="fw_upgrade_notice">您即将安装 %s 。</string>
<string name="fw_upgrade_notice_amazfitbip">即将在您的米手表青春版(Amazfit Bip)上安装固件 %s 。
\n
\n请确保安装.fw文件然后安装.res文件最后安装.gps文件。 安装.fw文件后手表将重新启动。
\n
\n注意如果这些文件与之前安装的完全一样则不必安装.res和.gps文件。
\n
<string name="fw_upgrade_notice_amazfitbip">即将在您的米手表青春版(Amazfit Bip)上安装固件 %s 。
\n
\n请确保安装.fw文件然后安装.res文件最后安装.gps文件。 安装.fw文件后手表将重新启动。
\n
\n注意如果这些文件与之前安装的完全一样则不必安装.res和.gps文件。
\n
\n***继续需要您自担风险!</string>
<string name="fw_upgrade_notice_amazfitcor">您即将在您的米手环(Amazfit Cor)上安装固件 %s 。
\n
\n请确保安装了 .fw 文件,然后安装 .rec 文件。 安装 .fw 文件后,手表将重新启动。
\n
\n注意如果这些文件与之前安装的完全一样则不必安装 .res 。
\n
<string name="fw_upgrade_notice_amazfitcor">您即将在您的米手环(Amazfit Cor)上安装固件 %s 。
\n
\n请确保安装了 .fw 文件,然后安装 .rec 文件。 安装 .fw 文件后,手表将重新启动。
\n
\n注意如果这些文件与之前安装的完全一样则不必安装 .res 。
\n
\n您需要自行承担风险</string>
<string name="fw_multi_upgrade_notice">您即将安装固件 %1$s 和 %2$s代替当前在小米手环上的固件。</string>
<string name="miband_firmware_known">该固件已经过测试,并且已知与 Gadgetbridge 兼容。</string>
@ -197,7 +197,7 @@
<string name="pairing_already_bonded">已与 %1$s (%2$s) 绑定,正在连接…</string>
<string name="message_cannot_pair_no_mac">没有 MAC 地址通过, 不能配对。</string>
<string name="preferences_category_device_specific_settings">设备特定设置</string>
<string name="preferences_miband_settings">小米手环/米手环设置</string>
<string name="preferences_miband_settings">小米手环/米手环设置</string>
<string name="male"></string>
<string name="female"></string>
<string name="other">其它</string>
@ -449,8 +449,8 @@
<string name="devicetype_unknown">未知设备</string>
<string name="devicetype_miband">小米手环</string>
<string name="devicetype_miband2">小米手环2</string>
<string name="devicetype_amazfit_bip">手表青春版</string>
<string name="devicetype_amazfit_cor">手环</string>
<string name="devicetype_amazfit_bip">米手表青春版</string>
<string name="devicetype_amazfit_cor">米手环</string>
<string name="pref_title_weather">天气</string>
<string name="vibration_profile_waterdrop">水滴</string>
<string name="devicetype_test">测试设备</string>
@ -684,14 +684,14 @@
<string name="pref_title_authkey">认证密钥</string>
<string name="pref_summary_authkey">将您想要连接的所有 Android 设备上的认证密钥更改为通用的密钥。默认所有设备的密钥是 0123456789@ABCDE</string>
<string name="devicetype_bfh16">BFH-16</string>
<string name="fw_upgrade_notice_amazfitcor2">您即将在米手环2(Amazfit Cor 2)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件
\n
\n风险自担
\n
<string name="fw_upgrade_notice_amazfitcor2">您即将在米手环2(Amazfit Cor 2)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件
\n
\n风险自担
\n
\n此功能未经测试如果您的设备名为“Amazfit Band 2”您可能需要刷入 BEATS_W 固件</string>
<string name="dutch">荷兰语</string>
<string name="turkish">土耳其语</string>
@ -701,7 +701,7 @@
<string name="thai">泰语</string>
<string name="vietnamese">越南语</string>
<string name="portuguese">葡萄牙语</string>
<string name="devicetype_amazfit_cor2">手环2</string>
<string name="devicetype_amazfit_cor2">米手环2</string>
<string name="devicetype_miband4">小米手环4</string>
<string name="fw_upgrade_notice_miband4">您即将在您的的小米手环4上安装 %s 固件。
\n
@ -756,27 +756,27 @@
<string name="activity_error_no_app_for_gpx">若需要查看活动轨迹,请安装一个能查看 GPX 文件的应用。</string>
<string name="preferences_makibes_hr3_settings">Makibes HR3 设置</string>
<string name="devicetype_makibes_hr3">Makibes HR3</string>
<string name="devicetype_amazfit_bip_lite">手表青春版 Lite</string>
<string name="devicetype_amazfit_bip_lite">米手表青春版 Lite</string>
<string name="prefs_find_phone">查找手机</string>
<string name="prefs_enable_find_phone">启用查找手机</string>
<string name="prefs_find_phone_summary">使用您的手环以在手机上播放铃声。</string>
<string name="prefs_find_phone_duration">铃声将持续数秒</string>
<string name="maximum_duration">持续</string>
<string name="discovery_need_to_enter_authkey">此设备需要认证密钥,请在设备上长按以输入密钥。具体请阅读 Wiki 。</string>
<string name="fw_upgrade_notice_amazfitbip_lite">您即将在米手表青春版 Lite(Amazfit Bip Lite)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件
\n
<string name="fw_upgrade_notice_amazfitbip_lite">您即将在米手表青春版 Lite(Amazfit Bip Lite)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件
\n
\n风险自担</string>
<string name="devicetype_amazfit_gtr">华米 GTR</string>
<string name="fw_upgrade_notice_amazfitgtr">即将在您的 华米 GTR (Amazfit GTR) 上安装固件 %s 。
\n
\n请确保先安装 .fw 文件,然后再安装 .res 文件,最后再安装 .gps 文件。您的手表将会安装了 .fw 文件后重启。
\n
\n注意如果 .res 和 .gps 文件和上一个版本相同,您则无需安装。
\n
<string name="fw_upgrade_notice_amazfitgtr">即将在您的华米 GTR (Amazfit GTR) 上安装固件 %s 。
\n
\n请确保先安装 .fw 文件,然后再安装 .res 文件,最后再安装 .gps 文件。您的手表将会安装了 .fw 文件后重启。
\n
\n注意如果 .res 和 .gps 文件和上一个版本相同,您则无需安装。
\n
\n风险自担</string>
<string name="pref_chart_heartrate_color_red"></string>
<string name="pref_chart_heartrate_color_orange"></string>
@ -784,13 +784,13 @@
<string name="pref_title_chart_sleep_rolling_24_hour">睡眠范围</string>
<string name="pref_chart_sleep_rolling_24_on">过去 24 小时</string>
<string name="pref_chart_sleep_rolling_24_off">中午到中午</string>
<string name="devicetype_amazfit_gts"> GTS</string>
<string name="fw_upgrade_notice_amazfitgts">您即将在 米动手表GTS(Amazfit GTS)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启。
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件。
\n
<string name="devicetype_amazfit_gts">米 GTS</string>
<string name="fw_upgrade_notice_amazfitgts">您即将在华米手表 GTS(Amazfit GTS)上安装 %s 版本的固件
\n
\n请确保先安装 .fw 文件,再安装 .res 文件。您的手环将会在安装了 .fw 文件后重启。
\n
\n备注如果您安装的 .res 文件和之前相同,则无需安装 .res 文件。
\n
\n风险自担</string>
<string name="mi2_prefs_button_press_broadcast_default_value" translatable="false">nodomain.freeyourgadget.gadgetbridge.ButtonPressed</string>
<string name="devicetype_qhybrid">Fossil Q Hybrid</string>
@ -847,4 +847,10 @@
<string name="pref_title_upper_button_function">上按钮</string>
<string name="pref_title_middle_button_function">中按钮</string>
<string name="pref_title_lower_button_function">下按钮</string>
<string name="pref_title_vibration_strength">振动强度</string>
<string name="devicetype_amazfit_bips">华米手表青春版 S</string>
<string name="pref_title_relax_firmware_checks">若您希望刷入并非为您设备设计的固件,请选中此项(风险自担)</string>
<string name="pref_summary_relax_firmware_checks">放宽固件检查</string>
<string name="pref_header_auto_fetch">自动获取</string>
<string name="pref_qhybrid_title_widget_draw_circles">绘制小部件圆圈</string>
</resources>

View File

@ -372,7 +372,7 @@
<string name="appmanager_weather_install_provider">安裝天氣通知應用程式</string>
<string name="app_move_to_top">移到最上方</string>
<string name="pref_title_notifications_repetitions">重複次數</string>
<string name="pref_summary_expose_hr">允許其他應用程式在裝置已連線時存取時心率資料</string>
<string name="pref_summary_expose_hr">允許其他應用程式在裝置已連線時存取時心率資料</string>
<string name="activity_prefs_alarm_max_heart_rate">最高心率</string>
<string name="zetime_prefs_inactivity_repetitions">重複次數</string>
<string name="appinstaller_install">安裝</string>
@ -468,4 +468,77 @@
<string name="hr_widget_weather">天氣</string>
<string name="find_lost_device_you_found_it">找到了!</string>
<string name="find_my_phone_notification">尋找我的手機</string>
<string name="devicetype_amazfit_bips">華米 Bip S</string>
<string name="hr_widget_nothing">沒有</string>
<string name="hr_widget_calories">卡路里</string>
<string name="error_no_location_access">位置存取權限必須被授予並啟用才能進行掃描</string>
<string name="devicetype_y5">Y5</string>
<string name="devicetype_banglejs">Bangle.js</string>
<string name="qhybrid_goal_in_steps">目標步數</string>
<string name="qhybrid_vibration_strength">振動強度:</string>
<string name="save_configuration">儲存設定</string>
<string name="toast_app_must_not_be_blacklisted">應用程式必須不在黑名單內才能設定</string>
<string name="preferences_fm_frequency">FM 頻率</string>
<string name="preferences_led_color">LED 顏色</string>
<string name="no_data">沒有資料</string>
<string name="watch9_time_seconds">秒:</string>
<string name="watch9_time_hours">小時:</string>
<string name="watch9_time_minutes">分鐘:</string>
<string name="menuitem_compass">羅盤</string>
<string name="notification_channel_name">Gadgetbridge 通知</string>
<string name="devicetype_roidmi3">睿米3</string>
<string name="devicetype_roidmi">睿米</string>
<string name="devicetype_watch9">Watch 9</string>
<string name="devicetype_mykronoz_zetime">MyKronoz ZeTime</string>
<string name="devicetype_no1_f1">No.1 F1</string>
<string name="devicetype_amazfit_bip">華米 Bip</string>
<string name="kind_invalid">無效的資料</string>
<string name="activity_type_walking">步行</string>
<string name="activity_type_running">跑步</string>
<string name="discovery_dont_pair">不配對</string>
<string name="discovery_pair_title">與%1$s進行配對\?</string>
<string name="discovery_attempting_to_pair">正在嘗試與%1$s進行配對</string>
<string name="mi2_enable_text_notifications">文字通知</string>
<string name="ok"></string>
<string name="activity_DB_delete_legacy_button">刪除舊的資料庫</string>
<string name="dbmanagementactivity_import_successful">已匯入。</string>
<string name="dbmanagementactivity_exported_to">已匯出到:%1$s</string>
<string name="updatefirmwareoperation_firmware_not_sent">韌體未傳送</string>
<string name="device_fw">韌體版本:%1$s</string>
<string name="authenticating">驗證中</string>
<string name="fwinstaller_firmware_not_compatible_to_device">此韌體與該裝置不相容</string>
<string name="miband_fwinstaller_incompatible_version">不相容的版本</string>
<string name="updatefirmwareoperation_write_failed">韌體安裝失敗</string>
<string name="updatefirmwareoperation_updateproblem_do_not_reboot">在傳輸韌體時發生問題。請勿重啟您的小米手環!</string>
<string name="fwapp_install_device_not_ready">檔案無法被安裝,裝置未就緒。</string>
<string name="chart_no_data_synchronize">尚無資料。同步裝置?</string>
<string name="pref_screen_notification_profile_calendar">日曆通知</string>
<string name="discovery_need_to_enter_authkey">此裝置需要一組驗證密鑰,在裝置上長按以進入設定。詳細資訊請閱讀專案 wiki。</string>
<string name="miband_pairing_tap_hint">當您的小米手環振動並閃爍時,請連續點擊數次。</string>
<string name="pairing_already_bonded">已與裝置 %1$s (%2$s) 完成綁定,連線中…</string>
<string name="title_activity_mi_band_pairing">配對您的小米手環</string>
<string name="title_activity_android_pairing">配對裝置</string>
<string name="initialized">初始化完成</string>
<string name="gadgetbridge_running">Gadgetbridge 正在執行</string>
<string name="tap_a_device_to_connect">點擊一個裝置以進行連線</string>
<string name="bluetooth_is_not_supported_">藍芽不支援。</string>
<string name="zetime_calories_type_all">涵蓋活動與未活動時消耗的卡路里</string>
<string name="zetime_calories_type_active">僅活動時消耗的卡路里</string>
<string name="zetime_calories_type">卡路里種類</string>
<string name="zetime_activity_tracking_summary">開啟活動追蹤將紀錄您的步數等資料。</string>
<string name="zetime_activity_tracking">活動追蹤</string>
<string name="zetime_heart_rate_alarm_enable">啟用心率警告</string>
<string name="zetime_title_heart_rate_alarm_summary">手錶將會在您的心率超過限制時警告您。</string>
<string name="zetime_title_heart_rate_alarm">心率警告</string>
<string name="pref_summary_use_custom_font">若您的裝置使用了自訂的字體以支援表情符號,請開啟此功能</string>
<string name="pref_title_use_custom_font">使用自訂字體</string>
<string name="pref_title_pebble_reconnect_attempts">重新連線嘗試次數</string>
<string name="pref_title_pebble_forceuntested">啟用尚未測試的功能</string>
<string name="pref_title_location_keep_uptodate">保持位置持續更新</string>
<string name="pref_title_location_latitude">緯度</string>
<string name="pref_title_location_aquire">取得位置</string>
<string name="pref_header_location">位置</string>
<string name="pref_title_enable_pebblekit">允許第三方 Android 應用程式存取</string>
<string name="pref_title_enable_outgoing_call">支援撥出電話</string>
<string name="title_activity_calblacklist">列入黑名單的日曆</string>
</resources>

View File

@ -186,6 +186,8 @@
<string name="pref_summary_allow_high_mtu">Increases transfer speed, but might not work on some Android devices.</string>
<string name="pref_summary_sync_calendar">Enables calendar alerts, even when disconnected</string>
<string name="pref_title_sync_caldendar">Sync calendar events</string>
<string name="pref_summary_relax_firmware_checks">Relax firmware checks</string>
<string name="pref_title_relax_firmware_checks">Enable this if you want to flash a firmware not intended for you device (at your own risk)</string>
<string name="pref_title_vibration_strength">Vibration strength</string>
<string name="pref_display_add_device_fab">Connect new device button</string>
<string name="pref_display_add_device_fab_on">Always visible</string>
@ -293,6 +295,7 @@
<string name="pref_title_auto_export_interval">Export interval</string>
<string name="pref_summary_auto_export_interval">Export every %d hour</string>
<!-- Auto fetch activity preferences -->
<string name="pref_header_auto_fetch">Auto fetch</string>
<string name="pref_auto_fetch">Auto fetch activity data</string>
<string name="pref_auto_fetch_summary">Fetch happens upon screen unlock. Only works if a lock mechanism is set!</string>
<string name="pref_auto_fetch_limit_fetches">Minimum time between fetches</string>
@ -717,6 +720,7 @@
<string name="devicetype_amazfit_cor">Amazfit Cor</string>
<string name="devicetype_amazfit_cor2">Amazfit Cor 2</string>
<string name="devicetype_amazfit_gtr">Amazfit GTR</string>
<string name="devicetype_amazfit_bips">Amazfit Bip S</string>
<string name="devicetype_vibratissimo">Vibratissimo</string>
<string name="devicetype_liveview">LiveView</string>
<string name="devicetype_hplus">HPlus</string>
@ -851,6 +855,7 @@
<string name="prefs_button_long_press_action_selection_title">Long press button action</string>
<string name="error_no_location_access">Location access must be granted and enabled for scanning to work properly</string>
<string name="pref_qhybrid_title_widget_draw_circles">Draw widget circles</string>
<plurals name="widget_alarm_target_hours">
<item quantity="one">%d hour</item>

View File

@ -1,5 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
<release version="0.43.2" versioncode="171">
<change>Fossil Hybrid HR: Allow choosing and cropping image to be set as watch background</change>
<change>Fossil Hybrid HR: Option to draw circles around widgets</change>
<change>Fossil Hybrid HR: Experimenal firmware update support</change>
<change>Fossil Hybrid HR: Fix vibration strength setting</change>
<change>Huami: Do not display firmware information and whitelist information when flashing watchfaces</change>
<change>Huami: Disable air quality indicator on Huami devices instead of showing 0</change>
<change>Bangle.js: Change encoded char set to match Espruino's 8 bit fonts</change>
<change>Steps/Sleep averages: Skip days with zero data</change>
</release>
<release version="0.43.1" versioncode="170">
<change>Initial support for Amazfit Bip S (incomplete, needs the official app once to obtain the pairing key)</change>
<change>Amazift Bip Lite: Allow relaxing firmware checks to allow flashing of the regular Bip firmware (for the brave)</change>
<change>Fossil Hybrid HR: Fix notification history on newer firmwares</change>
<change>Fossil Hybrid HR: Add option to disable widget circle</change>
<change>Bangle.js: Don't set time if the option is turned off in settings</change>
<change>Bangle.js: DST and time zone fixes</change>
<change>Add Arabic-style Eastern Arabic numerals to transliteration</change>
</release>
<release version="0.43.0" versioncode="169">
<change>Initial support for Fossil Hybrid HR (needs complicated key extraction, read wiki)</change>
<change>Fossil: Allow switching off the Q Icon and use the default Gadgetbridge icon</change>

View File

@ -27,9 +27,14 @@
android:key="force_white_color_scheme"
android:summary="@string/pref_summary_force_white_color_scheme"
android:title="@string/pref_title_force_white_color_scheme" />
<SwitchPreference
android:defaultValue="false"
android:key="widget_draw_circles"
android:title="@string/pref_qhybrid_title_widget_draw_circles" />
<SeekBarPreference
android:defaultValue="2"
android:key="@string/pref_title_vibration_strength"
android:key="vibration_strength"
android:max="3"
android:title="@string/pref_title_vibration_strength"
app:showSeekBarValue="true" />

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:defaultValue="false"
android:key="relax_firmware_checks"
android:summary="@string/pref_summary_relax_firmware_checks"
android:title="@string/pref_title_relax_firmware_checks" />
</androidx.preference.PreferenceScreen>

View File

@ -609,7 +609,7 @@
</PreferenceCategory>
<PreferenceCategory
android:title="Auto fetch">
android:title="@string/pref_header_auto_fetch">
<CheckBoxPreference
android:layout="@layout/preference_checkbox"
android:defaultValue="false"

View File

@ -6,6 +6,7 @@ import org.junit.Test;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.util.LanguageUtils;
import nodomain.freeyourgadget.gadgetbridge.util.KoreanLanguageUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -39,7 +40,7 @@ public class LanguageUtilsTest extends TestBase {
String pangram = "نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومغلف بجلد أزرق";
String pangramExpected = "n9 7kym lh sr qa63 wthw sh2n 36'ym mktwb 3la thwb 259'r wm3'lf bjld 2zrq";
String pangramActual = LanguageUtils.transliterate(pangram);
assertEquals("pangram transliteration failed", pangramExpected, pangramActual);
assertEquals("Arabic pangram transliteration failed", pangramExpected, pangramActual);
String taMarbutah = "";
String taMarbutahExpected = "";
@ -51,6 +52,14 @@ public class LanguageUtilsTest extends TestBase {
String hamzaActual = LanguageUtils.transliterate(hamza);
assertEquals("hamza transliteration failed", hamzaExpected, hamzaActual);
String easternArabicNumeralsArabic = "٠١٢٣٤٥٦٧٨٩";
String easternArabicNumeralsFarsi = "۰۱۲۳۴۵۶۷۸۹";
String easternArabicNumeralsExpected = "0123456789";
assertEquals("Eastern Arabic numerals (Arabic) failed", easternArabicNumeralsExpected,
LanguageUtils.transliterate(easternArabicNumeralsArabic));
assertEquals("Eastern Arabic numerals (Farsi) failed", easternArabicNumeralsExpected,
LanguageUtils.transliterate(easternArabicNumeralsFarsi));
String farsi = "گچپژ";
String farsiExpected = "gchpzh";
String farsiActual = LanguageUtils.transliterate(farsi);
@ -74,6 +83,43 @@ public class LanguageUtilsTest extends TestBase {
}
}
@Test
public void testStringTransliterateKorean() {
// A familiar phrase with no special provisions.
String hello = "안녕하세요";
String helloExpected = "annyeonghaseyo";
String helloActual = LanguageUtils.transliterate(hello);
assertEquals("Korean hello transliteration failed", helloExpected, helloActual);
// Korean pangram. Includes some ASCII punctuation which should not be changed by
// transliteration.
//
// Translation: "Chocolate!? What I wanted was some rice puffs and clothes." "Child, why are
// you complaining again?"
String pangram = "\"웬 초콜릿? 제가 원했던 건 뻥튀기 쬐끔과 의류예요.\" \"얘야, 왜 또 불평?\"";
String pangramExpected = "\"wen chokollit? jega wonhaetdeon geon ppeongtwigi jjoekkeumgwa uiryuyeyo.\" \"yaeya, wae tto bulpyeong?\"";
String pangramActual = LanguageUtils.transliterate(pangram);
assertEquals("Korean pangram transliteration failed", pangramExpected, pangramActual);
// Several words excercising special provisions, from Wikipedia.
String special = "좋고, 놓다, 잡혀, 낳지";
String specialExpected = "joko, nota, japhyeo, nachi";
String specialActual = LanguageUtils.transliterate(special);
assertEquals("Korean special provisions transliteration failed", specialExpected, specialActual);
// Isolated jamo.
String isolatedJamo = "ㅋㅋㅋ";
String isolatedJamoExpected = "kkk";
String isolatedJamoActual = LanguageUtils.transliterate(isolatedJamo);
assertEquals("Korean isolated jamo transliteration failed", isolatedJamoExpected, isolatedJamoActual);
// Korean transliteration shouldn't touch non-Hangul composites.
String german = "schön";
String germanExpected = german;
String germanActual = KoreanLanguageUtils.transliterate(german);
assertEquals("Korean transliteration modified a non-Hangul composite", germanExpected, germanActual);
}
@Test
public void testStringTransliterateLithuanian() {
String input = "ą č ę ė į š ų ū ž";

View File

@ -9,7 +9,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'com.android.tools.build:gradle:3.6.2'
classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:2.0.0"
// NOTE: Do not place your application dependencies here; they belong

View File

@ -0,0 +1,7 @@
* Initial support for Amazfit Bip S (incomplete, needs the official app once to obtain the pairing key)
* Amazift Bip Lite: Allow relaxing firmware checks to allow flashing of the regular Bip firmware (for the brave)
* Fossil Hybrid HR: Fix notification history on newer firmwares
* Fossil Hybrid HR: Add option to disable widget circle
* Bangle.js: Don't set time if the option is turned off in settings
* Bangle.js: DST and time zone fixes
* Add Arabic-style Eastern Arabic numerals to transliteration

View File

@ -0,0 +1,8 @@
* Fossil Hybrid HR: Allow choosing and cropping image to be set as watch background
* Fossil Hybrid HR: Option to draw circles around widgets
* Fossil Hybrid HR: Experimenal firmware update support
* Fossil Hybrid HR: Fix vibration strength setting
* Huami: Do not display firmware information and whitelist information when flashing watchfaces
* Huami: Disable air quality indicator on Huami devices instead of showing 0
* Bangle.js: Change encoded char set to match Espruino's 8 bit fonts
* Steps/Sleep averages: Skip days with zero data