diff --git a/CHANGELOG.md b/CHANGELOG.md index 996ab271c..aa203598c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ### Changelog +#### WIP +* Initial iTag support +* Fix indefinitely lasting bluetooth scans when location permission has not been granted +* Try to stop incoming VoIP call notification when the call is answered + #### Version 0.41.1 * Huami: allow to have alarms without snooze feature * Mi Band 2: Properly stop a call notification when text notifications are disabled diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index 0528c1c9b..d7256f6ff 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -43,7 +43,7 @@ public class GBDaoGenerator { public static void main(String[] args) throws Exception { - Schema schema = new Schema(23, MAIN_PACKAGE + ".entities"); + Schema schema = new Schema(24, MAIN_PACKAGE + ".entities"); Entity userAttributes = addUserAttributes(schema); Entity user = addUserInfo(schema, userAttributes); diff --git a/README.md b/README.md index 6fd40b58f..4cdefbedc 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ vendor's servers. * Casio GB-6900B * Fossil Q Hybrid * HPlus Devices (e.g. ZeBand) [Wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/HPlus) +* iTag * ID115 * JYou Y5 * Lenovo Watch 9 @@ -83,6 +84,7 @@ Please see [FEATURES.md](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/ma * Daniel Dakhno (Fossil Q Hybrid) * Gordon Williams (Bangle.js) * Pavel Elagin (JYou Y5) +* Taavi Eomäe (iTag) ## Contribute diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index dc8ca6043..4ed7b1acb 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -9,9 +9,26 @@ # Add any project specific keep options here: -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} +# Pebble BG-JS +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} +-keepclassmembers class nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.JSInterface { + public *; +} +-keepattributes JavascriptInterface + +# https://github.com/tony19/logback-android/issues/29 +-dontwarn javax.mail.**, javax.naming.Context, javax.naming.InitialContext + +# To avoid any stacktrace ambiguity +-keepattributes SourceFile,LineNumberTable + +# GreenDAO 2 - http://greenrobot.org/greendao/documentation/technical-faq/ +-keepclassmembers class * extends de.greenrobot.dao.AbstractDao { + public static java.lang.String TABLENAME; +} + +-keep class **$Properties + +-keep class **$Properties { *; } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java index 535bb3c95..5e7afd1f7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java @@ -53,6 +53,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -303,7 +304,13 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView registerReceiver(bluetoothReceiver, bluetoothIntents); - startDiscovery(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + GB.toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR); + LOG.error("No permission to access coarse location!"); + checkAndRequestLocationPermission(); + } else { + startDiscovery(); + } } @Override @@ -667,6 +674,7 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView bondingDevice = deviceCandidate; break; case BluetoothDevice.BOND_BONDED: + bondingDevice = deviceCandidate; handleDeviceBonded(); break; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java index cc24f2715..8963da73a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/devicesettings/DeviceSettingsPreferenceConst.java @@ -22,4 +22,5 @@ public class DeviceSettingsPreferenceConst { public static final String PREF_WEARLOCATION = "wearlocation"; public static final String PREF_SCREEN_ORIENTATION = "screen_orientation"; public static final String PREF_RESERVER_ALARMS_CALENDAR = "reserve_alarms_calendar"; + public static final String PREF_ALLOW_HIGH_MTU = "allow_high_mtu"; } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_24.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_24.java new file mode 100644 index 000000000..129d3ef40 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_24.java @@ -0,0 +1,35 @@ +/* Copyright (C) 2017-2020 Andreas Shimokawa, protomors + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.database.schema; + +import android.database.sqlite.SQLiteDatabase; + +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript; +import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao; + +public class GadgetbridgeUpdate_24 implements DBUpdateScript { + @Override + public void upgradeSchema(SQLiteDatabase db) { + // Probably it isbetter to hardcode then using constants since constants could change after refactoring and potentially break migration + db.execSQL("UPDATE DEVICE SET Type=170 where (Type=80 and Manufacturer like 'Fossil%')"); + } + + @Override + public void downgradeSchema(SQLiteDatabase db) { + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java index 0a00cb149..b1e22b125 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java @@ -97,7 +97,8 @@ public class MiBand4Coordinator extends HuamiCoordinator { R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_swipeunlock, R.xml.devicesettings_expose_hr_thirdparty, - R.xml.devicesettings_pairingkey + R.xml.devicesettings_pairingkey, + R.xml.devicesettings_high_mtu }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagConstants.java new file mode 100644 index 000000000..138af862d --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagConstants.java @@ -0,0 +1,24 @@ +/* Copyright (C) 2020 Taavi Eomäe + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.devices.itag; + +import java.util.UUID; + +public final class ITagConstants { + public static final UUID UUID_SERVICE_BUTTON = UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"); // Contains information about the button state + public static final UUID UUID_LINK_LOSS_ALERT_LEVEL = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb"); // Contains information about the button state +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagCoordinator.java new file mode 100644 index 000000000..5a65c8ce9 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/itag/ITagCoordinator.java @@ -0,0 +1,137 @@ +/* Copyright (C) 2016-2019 Andreas Shimokawa, Carsten Pfeiffer, Daniele Gobbetti, Taavi Eomäe + + 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 . +*/ +package nodomain.freeyourgadget.gadgetbridge.devices.itag; + +import android.app.Activity; +import android.content.Context; +import android.net.Uri; + +import androidx.annotation.NonNull; + +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +public class ITagCoordinator extends AbstractDeviceCoordinator { + @Override + @NonNull + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + String name = candidate.getDevice().getName(); + if (name != null && name.toLowerCase().startsWith("itag")) { // All four: iTAG, iTag, ITAG and ITag exist + return DeviceType.ITAG; + } + return DeviceType.UNKNOWN; + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.ITAG; + } + + @Override + public Class getPairingActivity() { + return null; + } + + @Override + public InstallHandler findInstallHandler(Uri uri, Context context) { + return null; + } + + @Override + public boolean supportsActivityDataFetching() { + return false; + } + + @Override + public boolean supportsActivityTracking() { + return false; + } + + @Override + public SampleProvider getSampleProvider(GBDevice device, DaoSession session) { + return null; + } + + @Override + public boolean supportsScreenshots() { + return false; + } + + @Override + public int getAlarmSlotCount() { + return 0; + } + + @Override + public boolean supportsSmartWakeup(GBDevice device) { + return false; + } + + @Override + public boolean supportsHeartRateMeasurement(GBDevice device) { + return false; + } + + @Override + public String getManufacturer() { + return "Unspecified"; //TODO: Show chip manufacturer? + } + + @Override + public boolean supportsAppsManagement() { + return false; + } + + @Override + public Class getAppsManagementActivity() { + return null; + } + + @Override + public boolean supportsCalendarEvents() { + return false; + } + + @Override + public boolean supportsRealtimeData() { + return false; //TODO: RRSI + } + + @Override + public boolean supportsWeather() { + return false; + } + + @Override + public boolean supportsFindDevice() { + return true; + } + + @Override + protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) { + // nothing to delete, yet + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index f01e51d52..a2de250a2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -116,6 +116,7 @@ public class NotificationListener extends NotificationListenerService { public static ArrayList notificationStack = new ArrayList<>(); private long activeCallPostTime; + private int mLastCallCommand = CallSpec.CALL_UNDEFINED; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -452,13 +453,20 @@ public class NotificationListener extends NotificationListenerService { } Notification noti = sbn.getNotification(); dumpExtras(noti.extras); + boolean callStarted = false; if(noti.actions != null && noti.actions.length > 0) { for (Notification.Action action : noti.actions) { LOG.info("Found call action: " + action.title); } if (noti.actions.length == 1) { - LOG.info("There is only one call action, assuming outgoing call and ignoring"); - return; + if (mLastCallCommand == CallSpec.CALL_INCOMING) { + LOG.info("There is only one call action and previous state was CALL_INCOMING, assuming call started"); + callStarted = true; + } else { + LOG.info("There is only one call action and previous state was not CALL_INCOMING, assuming outgoing call / duplicate notification and ignoring"); + // FIXME: is there a way to detect transition CALL_OUTGOING -> CALL_START for more complete VoIP call state tracking? + return; + } } /*try { LOG.info("Executing first action"); @@ -481,7 +489,8 @@ public class NotificationListener extends NotificationListenerService { activeCallPostTime = sbn.getPostTime(); CallSpec callSpec = new CallSpec(); callSpec.number = number; - callSpec.command = CallSpec.CALL_INCOMING; + callSpec.command = callStarted ? CallSpec.CALL_START : CallSpec.CALL_INCOMING; + mLastCallCommand = callSpec.command; GBApplication.deviceService().onSetCallState(callSpec); } @@ -653,6 +662,7 @@ public class NotificationListener extends NotificationListenerService { activeCallPostTime = 0; CallSpec callSpec = new CallSpec(); callSpec.command = CallSpec.CALL_END; + mLastCallCommand = callSpec.command; GBApplication.deviceService().onSetCallState(callSpec); } // FIXME: DISABLED for now diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CallSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CallSpec.java index 2e547f244..817ba872c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CallSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CallSpec.java @@ -17,7 +17,7 @@ package nodomain.freeyourgadget.gadgetbridge.model; public class CallSpec { - public static final int CALL_UNDEFINED = 1; + public static final int CALL_UNDEFINED = 0; public static final int CALL_ACCEPT = 1; public static final int CALL_INCOMING = 2; public static final int CALL_OUTGOING = 3; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java index dfea02556..e8b9e25e6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -52,18 +52,19 @@ public enum DeviceType { TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled, R.string.devicetype_teclast_h30), Y5(61, R.drawable.ic_device_h30_h10, R.drawable.ic_device_roidmi_disabled, R.string.devicetype_y5), XWATCH(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_xwatch), - FOSSILQHYBRID(80, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_qhybrid), ZETIME(80, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_mykronoz_zetime), ID115(90, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled, R.string.devicetype_id115), WATCH9(100, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_watch9), ROIDMI(110, R.drawable.ic_device_roidmi, R.drawable.ic_device_roidmi_disabled, R.string.devicetype_roidmi), ROIDMI3(112, R.drawable.ic_device_roidmi, R.drawable.ic_device_roidmi_disabled, R.string.devicetype_roidmi3), CASIOGB6900(120, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_casiogb6900), - MISCALE2(131, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_miscale2), + MISCALE2(131, R.drawable.ic_device_miscale2, R.drawable.ic_device_miscale2_disabled, R.string.devicetype_miscale2), BFH16(140, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_bfh16), MAKIBESHR3(150, R.drawable.ic_device_default, R.drawable.ic_device_hplus_disabled, R.string.devicetype_makibes_hr3), BANGLEJS(160, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_banglejs), + FOSSILQHYBRID(170, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_qhybrid), MIJIA_LYWSD02(200, R.drawable.ic_device_pebble, R.drawable.ic_device_pebble_disabled, R.string.devicetype_mijia_lywsd02), + ITAG(250, R.drawable.ic_device_itag, R.drawable.ic_device_itag_disabled, R.string.devicetype_itag), VIBRATISSIMO(300, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo), TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_test); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java index d5f17b733..858c34954 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -44,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitgts.Ama import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband3.MiBand3Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband4.MiBand4Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.id115.ID115Support; +import nodomain.freeyourgadget.gadgetbridge.service.devices.itag.ITagSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.BFH16DeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30.TeclastH30Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSupport; @@ -222,6 +223,9 @@ public class DeviceSupportFactory { case MAKIBESHR3: deviceSupport = new ServiceDeviceSupport(new MakibesHR3DeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; + case ITAG: + deviceSupport = new ServiceDeviceSupport(new ITagSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); + break; case BANGLEJS: deviceSupport = new ServiceDeviceSupport(new BangleJSDeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index 9fe2f3004..cee8549e9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -25,7 +25,6 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; -import android.text.format.DateFormat; import android.widget.Toast; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -55,7 +54,6 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity; -import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; @@ -136,6 +134,11 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; import nodomain.freeyourgadget.gadgetbridge.util.Version; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALLOW_HIGH_MTU; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_RESERVER_ALARMS_CALENDAR; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TIMEFORMAT; +import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_COUNT; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_PROFILE; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_COUNT; @@ -1250,6 +1253,10 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { case HuamiDeviceEvent.MTU_REQUEST: int mtu = (value[2] & 0xff) << 8 | value[1] & 0xff; LOG.info("device announced MTU of " + mtu); + Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())); + if (!prefs.getBoolean(PREF_ALLOW_HIGH_MTU, false)) { + break; + } mMTU = mtu; /* * not really sure if this would make sense, is this event already a proof of a successful MTU @@ -1673,7 +1680,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_3_CONFIGURATION); Prefs prefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())); - int availableSlots = prefs.getInt(DeviceSettingsPreferenceConst.PREF_RESERVER_ALARMS_CALENDAR, 0); + int availableSlots = prefs.getInt(PREF_RESERVER_ALARMS_CALENDAR, 0); if (availableSlots > 0) { CalendarEvents upcomingEvents = new CalendarEvents(); @@ -1747,10 +1754,10 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { case MiBandConst.PREF_SWIPE_UNLOCK: setBandScreenUnlock(builder); break; - case DeviceSettingsPreferenceConst.PREF_TIMEFORMAT: + case PREF_TIMEFORMAT: setTimeFormat(builder); break; - case DeviceSettingsPreferenceConst.PREF_DATEFORMAT: + case PREF_DATEFORMAT: setDateFormat(builder); break; case HuamiConst.PREF_LANGUAGE: @@ -1759,7 +1766,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { case HuamiConst.PREF_EXPOSE_HR_THIRDPARTY: setExposeHRThridParty(builder); break; - case DeviceSettingsPreferenceConst.PREF_WEARLOCATION: + case PREF_WEARLOCATION: setWearLocation(builder); break; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/itag/ITagSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/itag/ITagSupport.java new file mode 100644 index 000000000..923fbcf48 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/itag/ITagSupport.java @@ -0,0 +1,303 @@ +/* Copyright (C) 2016-2018 Andreas Shimokawa, Carsten Pfeiffer, Taavi Eomäe + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.itag; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.Uri; + +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; +import nodomain.freeyourgadget.gadgetbridge.devices.itag.ITagConstants; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.Alarm; +import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; +import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; +import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; +import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; +import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; +import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; +import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfoProfile; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile; + +public class ITagSupport extends AbstractBTLEDeviceSupport { + + private static final Logger LOG = LoggerFactory.getLogger(ITagSupport.class); + private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo(); + private final DeviceInfoProfile deviceInfoProfile; + private final BatteryInfoProfile batteryInfoProfile; + + private final IntentListener mListener = new IntentListener() { + @Override + public void notify(Intent intent) { + String s = intent.getAction(); + if (s.equals(DeviceInfoProfile.ACTION_DEVICE_INFO)) { + handleDeviceInfo((nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo) intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO)); + } else if (s.equals(BatteryInfoProfile.ACTION_BATTERY_INFO)) { + handleBatteryInfo((nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfo) intent.getParcelableExtra(BatteryInfoProfile.EXTRA_BATTERY_INFO)); + } + } + }; + + public ITagSupport() { + super(LOG); + addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS); + addSupportedService(GattService.UUID_SERVICE_GENERIC_ATTRIBUTE); + addSupportedService(GattService.UUID_SERVICE_BATTERY_SERVICE); + + addSupportedService(GattService.UUID_SERVICE_IMMEDIATE_ALERT); + addSupportedService(ITagConstants.UUID_SERVICE_BUTTON); + + + deviceInfoProfile = new DeviceInfoProfile<>(this); + deviceInfoProfile.addListener(mListener); + batteryInfoProfile = new BatteryInfoProfile<>(this); + batteryInfoProfile.addListener(mListener); + + addSupportedProfile(deviceInfoProfile); + addSupportedProfile(batteryInfoProfile); + } + + private void handleBatteryInfo(nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfo info) { + batteryCmd.level = (short) info.getPercentCharged(); + handleGBDeviceEvent(batteryCmd); + } + + @Override + protected TransactionBuilder initializeDevice(TransactionBuilder builder) { + builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); + requestDeviceInfo(builder); + setInitialized(builder); + batteryInfoProfile.requestBatteryInfo(builder); + return builder; + } + + private void requestDeviceInfo(TransactionBuilder builder) { + LOG.debug("Requesting device info!"); + deviceInfoProfile.requestDeviceInfo(builder); + } + + private void setInitialized(TransactionBuilder builder) { + builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); + } + + + @Override + public boolean useAutoConnect() { + return true; + } + + private void handleDeviceInfo(nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo info) { + + } + + @Override + public void onNotification(NotificationSpec notificationSpec) { + } + + @Override + public void onDeleteNotification(int id) { + + } + + @Override + public void onSetTime() { + + } + + @Override + public void onSetAlarms(ArrayList alarms) { + + } + + @Override + public void onSetCallState(CallSpec callSpec) { + + } + + @Override + public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) { + + } + + @Override + public void onSetMusicState(MusicStateSpec stateSpec) { + + } + + @Override + public void onSetMusicInfo(MusicSpec musicSpec) { + + } + + @Override + public void onEnableRealtimeSteps(boolean enable) { + + } + + @Override + public void onInstallApp(Uri uri) { + + } + + @Override + public void onAppInfoReq() { + + } + + @Override + public void onAppStart(UUID uuid, boolean start) { + + } + + @Override + public void onAppDelete(UUID uuid) { + + } + + @Override + public void onAppConfiguration(UUID appUuid, String config, Integer id) { + + } + + @Override + public void onAppReorder(UUID[] uuids) { + + } + + @Override + public void onFetchRecordedData(int dataTypes) { + + } + + @Override + public void onReset(int flags) { + + } + + @Override + public void onHeartRateTest() { + + } + + @Override + public void onEnableRealtimeHeartRateMeasurement(boolean enable) { + + } + + @Override + public void onFindDevice(boolean start) { + onSetConstantVibration(start ? 0x02 : 0x00); + } + + @Override + public void onSetConstantVibration(int intensity) { + getQueue().clear(); + BluetoothGattCharacteristic characteristic = getCharacteristic(ITagConstants.UUID_LINK_LOSS_ALERT_LEVEL); + + TransactionBuilder builder = new TransactionBuilder("beeping"); + builder.write(characteristic, new byte[]{(byte) intensity}); + builder.queue(getQueue()); + } + + @Override + public void onScreenshotReq() { + + } + + @Override + public void onEnableHeartRateSleepSupport(boolean enable) { + + } + + @Override + public void onSetHeartRateMeasurementInterval(int seconds) { + + } + + @Override + public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) { + + } + + @Override + public void onDeleteCalendarEvent(byte type, long id) { + + } + + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + if (super.onCharacteristicChanged(gatt, characteristic)) { + return true; + } + + UUID characteristicUUID = characteristic.getUuid(); + LOG.info("Unhandled characteristic changed: " + characteristicUUID); + return false; + } + + @Override + public boolean onCharacteristicRead(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, int status) { + if (super.onCharacteristicRead(gatt, characteristic, status)) { + return true; + } + UUID characteristicUUID = characteristic.getUuid(); + + LOG.info("Unhandled characteristic read: " + characteristicUUID); + return false; + } + + @Override + public void onSendConfiguration(String config) { + + } + + @Override + public void onReadConfiguration(String config) { + + } + + @Override + public void onTestNewFunction() { + + } + + @Override + public void onSendWeather(WeatherSpec weatherSpec) { + + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java index dd5a81954..f52a3292a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java @@ -467,7 +467,7 @@ class PebbleIoThread extends GBDeviceIoThread { write_real(bytes); } - // FIXME: parts are supporsed to be generic code + // FIXME: parts are supposed to be generic code private boolean evaluateGBDeviceEventPebble(GBDeviceEvent deviceEvent) { if (deviceEvent instanceof GBDeviceEventVersionInfo) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java index afcf04892..e904758d1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -50,6 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.hplus.MakibesF68Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipLiteCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgtr.AmazfitGTRCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitgts.AmazfitGTSCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.itag.ITagCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.makibeshr3.MakibesHR3Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.hplus.Q8Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipCoordinator; @@ -240,6 +241,7 @@ public class DeviceHelper { result.add(new CasioGB6900DeviceCoordinator()); result.add(new BFH16DeviceCoordinator()); result.add(new MijiaLywsd02Coordinator()); + result.add(new ITagCoordinator()); result.add(new MakibesHR3Coordinator()); result.add(new BangleJSCoordinator()); diff --git a/app/src/main/res/drawable-hdpi/ic_device_default.png b/app/src/main/res/drawable-hdpi/ic_device_default.png deleted file mode 100644 index 39682624c..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_device_default.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_device_default_disabled.png b/app/src/main/res/drawable-hdpi/ic_device_default_disabled.png deleted file mode 100644 index 1bac776d6..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_device_default_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_device_h30_h10.png b/app/src/main/res/drawable-hdpi/ic_device_h30_h10.png deleted file mode 100644 index 4a599d7b8..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_device_h30_h10.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_device_h30_h10_disabled.png b/app/src/main/res/drawable-hdpi/ic_device_h30_h10_disabled.png deleted file mode 100644 index f3da742ca..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_device_h30_h10_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_device_default.png b/app/src/main/res/drawable-mdpi/ic_device_default.png deleted file mode 100644 index 77c6f1829..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_device_default.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_device_default_disabled.png b/app/src/main/res/drawable-mdpi/ic_device_default_disabled.png deleted file mode 100644 index 8e63a4de1..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_device_default_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_device_h30_h10.png b/app/src/main/res/drawable-mdpi/ic_device_h30_h10.png deleted file mode 100644 index 729cbd624..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_device_h30_h10.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_device_h30_h10_disabled.png b/app/src/main/res/drawable-mdpi/ic_device_h30_h10_disabled.png deleted file mode 100644 index 72840f433..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_device_h30_h10_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_device_default.png b/app/src/main/res/drawable-xhdpi/ic_device_default.png deleted file mode 100644 index 1b45d346c..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_device_default.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_device_default_disabled.png b/app/src/main/res/drawable-xhdpi/ic_device_default_disabled.png deleted file mode 100644 index f345ede52..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_device_default_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_device_h30_h10.png b/app/src/main/res/drawable-xhdpi/ic_device_h30_h10.png deleted file mode 100644 index 5ce9b58e4..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_device_h30_h10.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_device_h30_h10_disabled.png b/app/src/main/res/drawable-xhdpi/ic_device_h30_h10_disabled.png deleted file mode 100644 index a3a55f5c4..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_device_h30_h10_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_device_default.png b/app/src/main/res/drawable-xxhdpi/ic_device_default.png deleted file mode 100644 index 57c0aeabf..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_device_default.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_device_default_disabled.png b/app/src/main/res/drawable-xxhdpi/ic_device_default_disabled.png deleted file mode 100644 index 4289e81fa..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_device_default_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10.png b/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10.png deleted file mode 100644 index 08f72ddbe..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10_disabled.png b/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10_disabled.png deleted file mode 100644 index 2d1d4eff1..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_device_h30_h10_disabled.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_device_default.xml b/app/src/main/res/drawable/ic_device_default.xml new file mode 100644 index 000000000..6a019f7bd --- /dev/null +++ b/app/src/main/res/drawable/ic_device_default.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_default_disabled.xml b/app/src/main/res/drawable/ic_device_default_disabled.xml new file mode 100644 index 000000000..b3a75ef29 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_default_disabled.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_h30_h10.xml b/app/src/main/res/drawable/ic_device_h30_h10.xml new file mode 100644 index 000000000..7c7e79e28 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_h30_h10.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_h30_h10_disabled.xml b/app/src/main/res/drawable/ic_device_h30_h10_disabled.xml new file mode 100644 index 000000000..0e2753a00 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_h30_h10_disabled.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_itag.xml b/app/src/main/res/drawable/ic_device_itag.xml new file mode 100644 index 000000000..95e1a19c7 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_itag.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_itag_disabled.xml b/app/src/main/res/drawable/ic_device_itag_disabled.xml new file mode 100644 index 000000000..1acdba6e2 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_itag_disabled.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_miscale2.xml b/app/src/main/res/drawable/ic_device_miscale2.xml new file mode 100644 index 000000000..2eb436c25 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_miscale2.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_device_miscale2_disabled.xml b/app/src/main/res/drawable/ic_device_miscale2_disabled.xml new file mode 100644 index 000000000..a3e717402 --- /dev/null +++ b/app/src/main/res/drawable/ic_device_miscale2_disabled.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 26c7baa83..293523f99 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -410,9 +410,9 @@ Akce tlačítka Nastavení akcí po stisknutí tlačítka Počet stisknutí tlačítka - Počet stisknutí tlačítka na spuštění vysílání zpráv + Počet stisknutí tlačítka pro vyvolání Události 1. Další stejné množství stisků vyvolá Událost 2 atd. Vysílání zpráv - Vysílání zprávy po definovaném počtu stisknutí tlačítka + Vysílání broadcast zprávy po při události. Parametr button_id je doplněn do každé zprávy automaticky. Zapnout akci tlačítka Zapnout akci na zadaný počet stisknutí tlačítka Zapnout vibrování náramku @@ -810,4 +810,13 @@ Zakázat nové BLE skenování Tuto možnost zaškrtněte pokud Vaše zařízení nelze najít během vyhledávání Bangle.js + Y5 + Akce události 1 + Akce události 2 + Akce události 3 + Detailní nastavení stisku tlačítka + Akce pro dlouhý stisk + Později... + 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í + iTag \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0ce07ea68..da1e0ef52 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -636,7 +636,7 @@ Modus-Konfiguration Konfiguration speichern Nicht verbunden, Alarm nicht eingestellt. - Benachichtigung beim Verbindung trennen + Benachrichtigung beim Verbindung trennen Tägliches Ziel: verbrannte Kalorien Tägliches Ziel: zurückgelegte Strecke in Meter Tägliches Ziel: aktive Zeit in Minuten @@ -825,4 +825,7 @@ Detaillierte Einstellungen zum Drücken von Tasten Langer Tastendruck Schlummern + Der Standortzugriff muss gewährt werden und aktiviert sein, damit das Scannen ordnungsgemäß funktioniert + iTag + Erhöht die Übertragungsgeschwindigkeit, funktioniert aber möglicherweise nicht auf einigen Android-Geräten. \ No newline at end of file diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 2b1971165..b8f6296dd 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -821,4 +821,8 @@ הגדרות נרחבות ללחיצת כפתור פעולה ללחיצה ארוכה על הכפתור נודניק + יש להעניק גישה למיקום כדי שהסריקה תעבוד כראוי + iTag + לאפשר MTU גבוה + מגביר את קצב ההעברה, יש מכשירי Android שלא תומכים בזה. \ No newline at end of file diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 025c92bfa..c3dedb461 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -821,4 +821,9 @@ Handling for hendelse 3 Detaljerte knappetrykksinnstillinger Handling for langt knappetrykk + Slumre + Plasseringstilgang må innvilges og skrus på for at skanning skal fungere + iTag + Tillat høy MTU + Øker overføringshastighet, men kan forårsake problemer på noen Android-enheter. \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 717ab35ed..860656371 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -4,7 +4,7 @@ Gadgetbridge Ustawienia Debuguj - Zamknij + Wyjdź Synchronizuj Znajdź zagubione urządzenie Zrób zrzut ekranu @@ -349,7 +349,7 @@ Połącz… Otwórz okno nawigacji Zamknij okno nawigacji - Kalibracja urządzenia + Skalibruj urządzenie Zablokuj wszystkie powiadomienia Zezwól na wszystkie powiadomienia Zamierzasz zainstalować firmware %s na swoim Amazfit Bip. @@ -379,7 +379,7 @@ Tryb prywatności połączeń telefonicznych Lokalizacja pogody (CM/LOS) Wyłączenie tej opcji spowoduje również, że Pebble 2/LE przestanie wibrować przy połączeniach wychodzących - Powiadomienia są automatycznie usuwane z Pebble po usunięciu ich z urządzenia Android + Powiadomienia są automatycznie usuwane z Pebble po usunięciu z urządzenia Android Przesuń tekst powiadomienia poza ekran Spróbuj pobrać obecną lokalizację po uruchomieniu, awaryjnie użyj zapisanej lokalizacji Zmień kolor diody LED @@ -768,7 +768,7 @@ Nie można skonfigurować aplikacji będącej na czarnej liście Wprowadź żądane wyrazy, każdy w nowej linii Zapisano filtr powiadomień - Blokuj, gdy zawiera słowa + Blokuj jeśli zawiera słowa Tryb filtrowania Ustawienia trybu Nie połączony, alarm nie ustawiony. @@ -778,7 +778,7 @@ Zabrzęcz raz Zabrzęcz dwa razy Wibracja i brzęczenie raz - Włącz powiadomienia o połączeniach z aplikacji VoIP + Włącz VoIP połączenia Zmień klucz autoryzacji na wspólny dla wszystkich urządzeń z Androidem, z których chcesz się połączyć. Poprzedni domyślny klucz dla wszystkich urządzeń to 0123456789@ABCDE Alarm tętna podczas aktywności sportowej Dolny limit @@ -817,4 +817,10 @@ Akcja zdarzenia 3 Szczegółowe ustawienia naciśnięcia przycisku Akcja przytrzymania przycisku + Przeglądanie aktywności w sieci + Zresetuj datę pobierania + Monitirowanie aktywności, liczy twoje kroki i inne. + przesunięcie czasowe + użyj ręki aktywności jako licznika powiadomień + iTag \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3477ffa01..57d594b81 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -831,4 +831,8 @@ Configurações detalhado de pressionamento de botão Ação do botão de pressionamento longo Adiar + Acesso a localização deve ser concedido e habilitado para varredura funcionar adequadamente + iTag + Permitir MTU alto + Aumenta velocidade de transferência, mas pode não funcionar em alguns dispositivos Android. \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 1e77ee82e..411dc2219 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -29,12 +29,12 @@ Перелік заблокованих сповіщень Встановлення мікропрограми - Ви збираєтесь встановити мікропрограму %s на заміну поточній Вашого Mi–Band. + Ви збираєтесь встановити %s. Ви збираєтесь встановити прошивки %1$s та %2$s на заміну поточній вашого Mi Band. Ця мікропрограма була перевірена на сумісність із Gadgetbridge. Ця мікропрограма не перевірялася і може бути не сумісною із Gadgetbridge. \n -\nНе рекомендується встановлювати її на Ваш Mi Band! +\nНе рекомендується встановлювати її! Якщо ж Ви вирішили продовжити та все працює, будь ласка, повідомте про це розробникам, аби відмітити версію %s мікропрограми сумісною з вашим пристроєм. Параметри @@ -67,7 +67,7 @@ Відповіді Загальний суфікс Параметри для розробників - MAC адреса Mi Band + Адреса Mi Band Параметри Pebble Трекер активності Бажаний трекер активності @@ -153,7 +153,7 @@ Соціальні мережі Знайти загублений пристрій Скасуйте, аби зупинити вібрацію. - Ваша активність + Активність і сон Завести Будильник Завести будильник Деталі будильнику @@ -181,9 +181,9 @@ %1$s заряду лишилось: %2$s%% Остання зарядка була: %s \n Кількість зарядок: %s - Ваш сон + Сон Кроків за тиждень - Ваша активність та сон + Активність Завантаження мікропрограми… Не можливо встановити файл, пристрій не готовий. %1$s: %2$s %3$s @@ -213,7 +213,7 @@ Активність Швидкий сон Глибокий сон - + Не носили Не з\'єднано. Всі будильники вимкнено Лишати дані на пристрої @@ -242,9 +242,9 @@ Відкрити навігаційну панель Закрити навігаційну панель Роз\'єднання - Довго натисніть на картку, щоб Роз\'єднати + Нажміть і тримайте для роз\'єднання Знімок екрана пристрою - Додатки в кеші + Додатки в пам\'яті Встановлені годинники Активувати системний додаток погоди Вимкнути системний додаток погоди @@ -360,7 +360,7 @@ Всього хвилин Сон за тиждень Сон сьогодні, ціль: %1$s - Змінити колір світлодіода + Змінити колір LED Змінити частоту FM Дійсно скинути до заводських налаштувань\? З права на ліво @@ -466,4 +466,156 @@ ДД/ММ/РР ММ/ДД/РР nodomain.freeyourgadget.gadgetbridge.ButtonPressed + Ужити експериментальну підтримку Pebble LE для всіх Pebbles замість BT classic. Потребує парування спочатку з не-LE, а потім з Pebble LE + Обмеження GATT MTU для Pebble 2/LE + Якщо ваш Pebble 2/LE не працює, спробуйте це налаштування щоб обмежити MTU (в діапазоні 20-512) + Логи аплікації годинника будуть записані Gadgetbridge (потребує перепідключення) + Передчасний ACK PebbleKit + Повідомлення які надіслано стороннім зовнішнім аплікаціям буде завжди і одразу підтвердженно + Торкніться під\'єднаного пристрою для виклику Менеджера аплікації + Торкніться під\'єднаного пристрою для виклику Діяльності + Зв\'язуюсь з %1$s (%2$s) + Вже пов\'язаний з %1$s (%2$s), під\'єднуюсь… + Зберігати файли логів + Зони швидкості + Зміщення часу в годинах (для тих, хто працює по ночах) + Повідомлення по мету + Відображати + Увімкнути екран при піднесенні + Не турбувати + Попередження про неактивність + Поріг неактивності (хв) + Початок + Завершення + Авторизація + Потрібна авторизація + Бажана довжина сну в годинах + Записування прошивки + Прошивку не відправлено + Пульс + Пульс + Керування базою даних + Керування базою даних + Видалення застарілою бази даних + Експортовано до: %1$s + Помилка експорту бази: %1$s + Помилка експорту налаштувань: %1$s + Дія кнопки + Виберіть дію при натисненні + Натиснень на кнопку + Повідомлення для поширення + Увімкнути кнопку дії + Увімкнути вібрацію паску + Коли увімкнено, дозволяє циферблату показувати погоду, заряд батареї і т.п. + Автоматично + Спрощена китайська + Традиційна китайська + Англійська + Цілодобове вимірювання пульсу + Автоматичний експорт + Розташування експорту + Інтервал експорту + Експорт кожні %d годин(и) + Іспанська + Тільки клієнт GATT + Це експериментальне налаштування виключно для Pebble 2, застосуйте якщо є проблеми з підключенням + Авто-завантаження даних про активність + Мінімальний час між щавантаженням + Отримати кожні %d хвилин(и) + Російська + Німецька + Італійська + Французька + Польська + Корейська + Японська + Ви спали з %1$s до %2$s + Норвезький літературний + Нічний режим + Налаштування графіків + Максимальний пульс + Мінімальний пульс + %1$s низький заряд + %1$s низький заряд: %2$s + Увімкніть, якщо ваш пристрій не відображає мови \"зправа наліво\" + Максимальна довжина строки \"зправа наліво\" + Подовжує чи скорочує строки на які розбитий текст \"зправа наліво\" + Недосипання: %1$s + Пересип: %1$s + Недостатньо кроків: %1$d + Поточний / максимальний пульс: %1$d / %2$d + Скидання до заводських налаштувань призведе до видалення всіх даних з під\'єднаного пристрою (якщо підтримується). Xiaomi/Huami пристрої також змінять свою Bluetooth MAC адресу, тому вони з\'являться як нові пристрої для Gadgetbridge. + Повідомлення про від\'єднання + Попередження про пульс + Годинник повідомить вас, коли перевищено показник пульсу. + Увімкнути попередження про пульс + Руки і кроки + Відслідковування діяльності + Увімкнення відслідковування діяльності, буде рахувати кроки та ін. + Рух руки + Поверніть зап\'ястя для увімкнення/вимкнення дисплею. + Тип калорій + Тільки активно спалені калорії + Активно і неактивно спалені калорії + Повторення + Понеділок + Вівторек + Середа + Четвер + П\'ятниця + Субота + Неділя + Вкажіть спосіб повідомлення про будильник + Тихо + Постійна вібрація + Постійний звук + Постійна вібрація і звук + Пискнути раз + Пискнути двічі + Повідослення про пропущені дзвінки + Повідомлення календарю + Повідомлення про бездіяльність + Попередження про низький заряд + Попередження про втрату + кожні 15 хв + кожні 45 хв + Увімкніть VoIP дзвінки + Налаштування конкретних пристроїв + Ключ авторизації + Дацька + Турецька + Українська + Арабська + Індонезійська + Тайська + В\'єтнамська + Португальська + Попередження про пульс під час зайнять спортом + Нижня границя + Верхня границя + В середньому: %1$s + Налаштування графіків + Діапазон графікав + Кроків за місяць + Сон за місяць + Дозволяє іншим аплікаціям постійно отримувати дані про пульс, поки Gadgetbridge під\'єднано + Доступ до пульсометру сторонніх аплікацій + Нестандартний шрифт + Увімкніть, якщо ваш пристрій має нестандартну програму для підтримки емоджи + Експортувати базу даних + Імпортувати базу даних + Кнопка підключення нового пристрою + Завжди видно + Видно якщо не додано пристрій + Налаштування Makibes HR3 + Знайти телефон + Червоний + Помаранчевий + Колір пульсу + Діапазон сну + Останні 24 години + Полудень до полудня + Вимкнути пошук нових BLE + Увімкніть, якщо ваш пристрій не знайдено під час пошуку + Затримати \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 4b57987d6..aab68a7e6 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -819,4 +819,8 @@ 按下按钮时的详细设置 长按按钮的动作 打盹 + 为确保工作正常必须授权地理位置访问和扫描 + iTag + 允许高 MTU + 增加传输速度,但是在某些 Android 设备上可能不会工作。 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b2a2cab7..778a70c97 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -180,6 +180,8 @@ 3rd party realtime HR access Use custom font Enable this if your device has a custom font firmware for emoji support + Allow high MTU + Increases transfer speed, but might not work on some Android devices. Connect new device button Always visible Visible only if no device is added @@ -686,6 +688,7 @@ Y5 Casio GB-6900 Mi Scale 2 + iTag BFH-16 Mijia Smart Clock Makibes HR3 @@ -787,6 +790,8 @@ Detailed button press settings Long press button action + Location access must be granted and enabled for scanning to work properly + %d hour %d hours diff --git a/app/src/main/res/xml/devicesettings_high_mtu.xml b/app/src/main/res/xml/devicesettings_high_mtu.xml new file mode 100644 index 000000000..9751da642 --- /dev/null +++ b/app/src/main/res/xml/devicesettings_high_mtu.xml @@ -0,0 +1,8 @@ + + + +