1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-30 14:02:56 +01:00

Clean-up the merge.

This commit is contained in:
Sebastian Kranz 2018-06-29 11:18:36 +02:00
parent 1b152c86ea
commit 59095dc29b
6 changed files with 10 additions and 1558 deletions

View File

@ -1,365 +0,0 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nodomain.freeyourgadget.gadgetbridge.daogen;
import java.util.Date;
import de.greenrobot.daogenerator.DaoGenerator;
import de.greenrobot.daogenerator.Entity;
import de.greenrobot.daogenerator.Index;
import de.greenrobot.daogenerator.Property;
import de.greenrobot.daogenerator.Schema;
/**
* Generates entities and DAOs for the example project DaoExample.
* Automatically run during build.
*/
public class GBDaoGenerator {
private static final String VALID_FROM_UTC = "validFromUTC";
private static final String VALID_TO_UTC = "validToUTC";
private static final String MAIN_PACKAGE = "nodomain.freeyourgadget.gadgetbridge";
private static final String MODEL_PACKAGE = MAIN_PACKAGE + ".model";
private static final String VALID_BY_DATE = MODEL_PACKAGE + ".ValidByDate";
private static final String ACTIVITY_SUMMARY = MODEL_PACKAGE + ".ActivitySummary";
private static final String OVERRIDE = "@Override";
private static final String SAMPLE_RAW_INTENSITY = "rawIntensity";
private static final String SAMPLE_STEPS = "steps";
private static final String SAMPLE_RAW_KIND = "rawKind";
private static final String SAMPLE_HEART_RATE = "heartRate";
private static final String TIMESTAMP_FROM = "timestampFrom";
private static final String TIMESTAMP_TO = "timestampTo";
public static void main(String[] args) throws Exception {
Schema schema = new Schema(18, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
Entity deviceAttributes = addDeviceAttributes(schema);
Entity device = addDevice(schema, deviceAttributes);
// yeah deep shit, has to be here (after device) for db upgrade and column order
// because addDevice adds a property to deviceAttributes also....
deviceAttributes.addStringProperty("volatileIdentifier");
Entity tag = addTag(schema);
Entity userDefinedActivityOverlay = addActivityDescription(schema, tag, user);
addMiBandActivitySample(schema, user, device);
addPebbleHealthActivitySample(schema, user, device);
addPebbleHealthActivityKindOverlay(schema, user, device);
addPebbleMisfitActivitySample(schema, user, device);
addPebbleMorpheuzActivitySample(schema, user, device);
addHPlusHealthActivityKindOverlay(schema, user, device);
addHPlusHealthActivitySample(schema, user, device);
addNo1F1ActivitySample(schema, user, device);
<<<<<<< HEAD
addZeTimeActivitySample(schema, user, device);
=======
addXWatchActivitySample(schema, user, device);
>>>>>>> master
addCalendarSyncState(schema, device);
addBipActivitySummary(schema, user, device);
new DaoGenerator().generateAll(schema, "app/src/main/java");
}
private static Entity addTag(Schema schema) {
Entity tag = addEntity(schema, "Tag");
tag.addIdProperty();
tag.addStringProperty("name").notNull();
tag.addStringProperty("description").javaDocGetterAndSetter("An optional description of this tag.");
tag.addLongProperty("userId").notNull();
return tag;
}
private static Entity addActivityDescription(Schema schema, Entity tag, Entity user) {
Entity activityDesc = addEntity(schema, "ActivityDescription");
activityDesc.setJavaDoc("A user may further specify his activity with a detailed description and the help of tags.\nOne or more tags can be added to a given activity range.");
activityDesc.addIdProperty();
activityDesc.addIntProperty(TIMESTAMP_FROM).notNull();
activityDesc.addIntProperty(TIMESTAMP_TO).notNull();
activityDesc.addStringProperty("details").javaDocGetterAndSetter("An optional detailed description, specific to this very activity occurrence.");
Property userId = activityDesc.addLongProperty("userId").notNull().getProperty();
activityDesc.addToOne(user, userId);
Entity activityDescTagLink = addEntity(schema, "ActivityDescTagLink");
activityDescTagLink.addIdProperty();
Property sourceId = activityDescTagLink.addLongProperty("activityDescriptionId").notNull().getProperty();
Property targetId = activityDescTagLink.addLongProperty("tagId").notNull().getProperty();
activityDesc.addToMany(tag, activityDescTagLink, sourceId, targetId);
return activityDesc;
}
private static Entity addUserInfo(Schema schema, Entity userAttributes) {
Entity user = addEntity(schema, "User");
user.addIdProperty();
user.addStringProperty("name").notNull();
user.addDateProperty("birthday").notNull();
user.addIntProperty("gender").notNull();
Property userId = userAttributes.addLongProperty("userId").notNull().getProperty();
// sorted by the from-date, newest first
Property userAttributesSortProperty = getPropertyByName(userAttributes, VALID_FROM_UTC);
user.addToMany(userAttributes, userId).orderDesc(userAttributesSortProperty);
return user;
}
private static Property getPropertyByName(Entity entity, String propertyName) {
for (Property prop : entity.getProperties()) {
if (propertyName.equals(prop.getPropertyName())) {
return prop;
}
}
throw new IllegalStateException("Could not find property " + propertyName + " in entity " + entity.getClassName());
}
private static Entity addUserAttributes(Schema schema) {
// additional properties of a user, which may change during the lifetime of a user
// this allows changing attributes while preserving user identity
Entity userAttributes = addEntity(schema, "UserAttributes");
userAttributes.addIdProperty();
userAttributes.addIntProperty("heightCM").notNull();
userAttributes.addIntProperty("weightKG").notNull();
userAttributes.addIntProperty("sleepGoalHPD").javaDocGetterAndSetter("Desired number of hours of sleep per day.");
userAttributes.addIntProperty("stepsGoalSPD").javaDocGetterAndSetter("Desired number of steps per day.");
addDateValidityTo(userAttributes);
return userAttributes;
}
private static void addDateValidityTo(Entity entity) {
entity.addDateProperty(VALID_FROM_UTC).codeBeforeGetter(OVERRIDE);
entity.addDateProperty(VALID_TO_UTC).codeBeforeGetter(OVERRIDE);
entity.implementsInterface(VALID_BY_DATE);
}
private static Entity addDevice(Schema schema, Entity deviceAttributes) {
Entity device = addEntity(schema, "Device");
device.addIdProperty();
device.addStringProperty("name").notNull();
device.addStringProperty("manufacturer").notNull();
device.addStringProperty("identifier").notNull().unique().javaDocGetterAndSetter("The fixed identifier, i.e. MAC address of the device.");
device.addIntProperty("type").notNull().javaDocGetterAndSetter("The DeviceType key, i.e. the GBDevice's type.");
device.addStringProperty("model").javaDocGetterAndSetter("An optional model, further specifying the kind of device-");
Property deviceId = deviceAttributes.addLongProperty("deviceId").notNull().getProperty();
// sorted by the from-date, newest first
Property deviceAttributesSortProperty = getPropertyByName(deviceAttributes, VALID_FROM_UTC);
device.addToMany(deviceAttributes, deviceId).orderDesc(deviceAttributesSortProperty);
return device;
}
private static Entity addDeviceAttributes(Schema schema) {
Entity deviceAttributes = addEntity(schema, "DeviceAttributes");
deviceAttributes.addIdProperty();
deviceAttributes.addStringProperty("firmwareVersion1").notNull();
deviceAttributes.addStringProperty("firmwareVersion2");
addDateValidityTo(deviceAttributes);
return deviceAttributes;
}
private static Entity addMiBandActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "MiBandActivitySample");
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
addHeartRateProperties(activitySample);
return activitySample;
}
private static void addHeartRateProperties(Entity activitySample) {
activitySample.addIntProperty(SAMPLE_HEART_RATE).notNull().codeBeforeGetterAndSetter(OVERRIDE);
}
private static Entity addPebbleHealthActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "PebbleHealthActivitySample");
addCommonActivitySampleProperties("AbstractPebbleHealthActivitySample", activitySample, user, device);
activitySample.addByteArrayProperty("rawPebbleHealthData").codeBeforeGetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
addHeartRateProperties(activitySample);
return activitySample;
}
private static Entity addPebbleHealthActivityKindOverlay(Schema schema, Entity user, Entity device) {
Entity activityOverlay = addEntity(schema, "PebbleHealthActivityOverlay");
activityOverlay.addIntProperty(TIMESTAMP_FROM).notNull().primaryKey();
activityOverlay.addIntProperty(TIMESTAMP_TO).notNull().primaryKey();
activityOverlay.addIntProperty(SAMPLE_RAW_KIND).notNull().primaryKey();
Property deviceId = activityOverlay.addLongProperty("deviceId").primaryKey().notNull().getProperty();
activityOverlay.addToOne(device, deviceId);
Property userId = activityOverlay.addLongProperty("userId").notNull().getProperty();
activityOverlay.addToOne(user, userId);
activityOverlay.addByteArrayProperty("rawPebbleHealthData");
return activityOverlay;
}
private static Entity addPebbleMisfitActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "PebbleMisfitSample");
addCommonActivitySampleProperties("AbstractPebbleMisfitActivitySample", activitySample, user, device);
activitySample.addIntProperty("rawPebbleMisfitSample").notNull().codeBeforeGetter(OVERRIDE);
return activitySample;
}
private static Entity addPebbleMorpheuzActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "PebbleMorpheuzSample");
addCommonActivitySampleProperties("AbstractPebbleMorpheuzActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
return activitySample;
}
private static Entity addHPlusHealthActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "HPlusHealthActivitySample");
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device);
activitySample.addByteArrayProperty("rawHPlusHealthData");
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().primaryKey();
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
addHeartRateProperties(activitySample);
activitySample.addIntProperty("distance");
activitySample.addIntProperty("calories");
return activitySample;
}
private static Entity addHPlusHealthActivityKindOverlay(Schema schema, Entity user, Entity device) {
Entity activityOverlay = addEntity(schema, "HPlusHealthActivityOverlay");
activityOverlay.addIntProperty(TIMESTAMP_FROM).notNull().primaryKey();
activityOverlay.addIntProperty(TIMESTAMP_TO).notNull().primaryKey();
activityOverlay.addIntProperty(SAMPLE_RAW_KIND).notNull().primaryKey();
Property deviceId = activityOverlay.addLongProperty("deviceId").primaryKey().notNull().getProperty();
activityOverlay.addToOne(device, deviceId);
Property userId = activityOverlay.addLongProperty("userId").notNull().getProperty();
activityOverlay.addToOne(user, userId);
activityOverlay.addByteArrayProperty("rawHPlusHealthData");
return activityOverlay;
}
private static Entity addNo1F1ActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "No1F1ActivitySample");
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
addHeartRateProperties(activitySample);
return activitySample;
}
<<<<<<< HEAD
private static Entity addZeTimeActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "ZeTimeActivitySample");
=======
private static Entity addXWatchActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "XWatchActivitySample");
>>>>>>> master
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_INTENSITY).notNull().codeBeforeGetterAndSetter(OVERRIDE);
addHeartRateProperties(activitySample);
return activitySample;
}
private static void addCommonActivitySampleProperties(String superClass, Entity activitySample, Entity user, Entity device) {
activitySample.setSuperclass(superClass);
activitySample.addImport(MAIN_PACKAGE + ".devices.SampleProvider");
activitySample.setJavaDoc(
"This class represents a sample specific to the device. Values like activity kind or\n" +
"intensity, are device specific. Normalized values can be retrieved through the\n" +
"corresponding {@link SampleProvider}.");
activitySample.addIntProperty("timestamp").notNull().codeBeforeGetterAndSetter(OVERRIDE).primaryKey();
Property deviceId = activitySample.addLongProperty("deviceId").primaryKey().notNull().codeBeforeGetterAndSetter(OVERRIDE).getProperty();
activitySample.addToOne(device, deviceId);
Property userId = activitySample.addLongProperty("userId").notNull().codeBeforeGetterAndSetter(OVERRIDE).getProperty();
activitySample.addToOne(user, userId);
}
private static void addCalendarSyncState(Schema schema, Entity device) {
Entity calendarSyncState = addEntity(schema, "CalendarSyncState");
calendarSyncState.addIdProperty();
Property deviceId = calendarSyncState.addLongProperty("deviceId").notNull().getProperty();
Property calendarEntryId = calendarSyncState.addLongProperty("calendarEntryId").notNull().getProperty();
Index indexUnique = new Index();
indexUnique.addProperty(deviceId);
indexUnique.addProperty(calendarEntryId);
indexUnique.makeUnique();
calendarSyncState.addIndex(indexUnique);
calendarSyncState.addToOne(device, deviceId);
calendarSyncState.addIntProperty("hash").notNull();
}
private static void addBipActivitySummary(Schema schema, Entity user, Entity device) {
Entity summary = addEntity(schema, "BaseActivitySummary");
summary.implementsInterface(ACTIVITY_SUMMARY);
summary.addIdProperty();
summary.setJavaDoc(
"This class represents the summary of a user's activity event. I.e. a walk, hike, a bicycle tour, etc.");
summary.addStringProperty("name").codeBeforeGetter(OVERRIDE);
summary.addDateProperty("startTime").notNull().codeBeforeGetter(OVERRIDE);
summary.addDateProperty("endTime").notNull().codeBeforeGetter(OVERRIDE);
summary.addIntProperty("activityKind").notNull().codeBeforeGetter(OVERRIDE);
summary.addIntProperty("baseLongitude").javaDocGetterAndSetter("Temporary, bip-specific");
summary.addIntProperty("baseLatitude").javaDocGetterAndSetter("Temporary, bip-specific");
summary.addIntProperty("baseAltitude").javaDocGetterAndSetter("Temporary, bip-specific");
summary.addStringProperty("gpxTrack").codeBeforeGetter(OVERRIDE);
Property deviceId = summary.addLongProperty("deviceId").notNull().codeBeforeGetter(OVERRIDE).getProperty();
summary.addToOne(device, deviceId);
Property userId = summary.addLongProperty("userId").notNull().codeBeforeGetter(OVERRIDE).getProperty();
summary.addToOne(user, userId);
}
private static Property findProperty(Entity entity, String propertyName) {
for (Property prop : entity.getProperties()) {
if (propertyName.equals(prop.getPropertyName())) {
return prop;
}
}
throw new IllegalArgumentException("Property " + propertyName + " not found in Entity " + entity.getClassName());
}
private static Entity addEntity(Schema schema, String className) {
Entity entity = schema.addEntity(className);
entity.addImport("de.greenrobot.dao.AbstractDao");
return entity;
}
}

View File

@ -1,101 +0,0 @@
/* Copyright (C) 2015-2018 Andreas Shimokawa, Carsten Pfeiffer, Daniele
Gobbetti, João Paulo Barraca, ladbsoft, protomors, Quallenauge, Sami
Alaoui, tiparega
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.model;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import nodomain.freeyourgadget.gadgetbridge.R;
/**
* For every supported device, a device type constant must exist.
*
* Note: they key of every constant is stored in the DB, so it is fixed forever,
* and may not be changed.
*/
public enum DeviceType {
UNKNOWN(-1, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_unknown),
PEBBLE(1, R.drawable.ic_device_pebble, R.drawable.ic_device_pebble_disabled, R.string.devicetype_pebble),
MIBAND(10, R.drawable.ic_device_miband, R.drawable.ic_device_miband_disabled, R.string.devicetype_miband),
MIBAND2(11, R.drawable.ic_device_miband, R.drawable.ic_device_miband_disabled, R.string.devicetype_miband2),
AMAZFITBIP(12, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_bip),
AMAZFITCOR(13, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_amazfit_cor),
MIBAND3(14, R.drawable.ic_device_miband, R.drawable.ic_device_miband_disabled, R.string.devicetype_miband3),
VIBRATISSIMO(20, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo),
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),
EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_exrizu_k8),
Q8(43, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_q8),
NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_no1_f1),
TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled, R.string.devicetype_teclast_h30),
<<<<<<< HEAD
ZETIME(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_mykronoz_zetime),
=======
XWATCH(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_xwatch),
>>>>>>> master
TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_test);
private final int key;
@DrawableRes
private final int defaultIcon;
@DrawableRes
private final int disabledIcon;
@StringRes
private final int name;
DeviceType(int key, int defaultIcon, int disabledIcon, int name) {
this.key = key;
this.defaultIcon = defaultIcon;
this.disabledIcon = disabledIcon;
this.name = name;
}
public int getKey() {
return key;
}
public boolean isSupported() {
return this != UNKNOWN;
}
public static DeviceType fromKey(int key) {
for (DeviceType type : values()) {
if (type.key == key) {
return type;
}
}
return DeviceType.UNKNOWN;
}
@StringRes
public int getName() {
return name;
}
@DrawableRes
public int getIcon() {
return defaultIcon;
}
@DrawableRes
public int getDisabledIcon() {
return disabledIcon;
}
}

View File

@ -1,186 +0,0 @@
/* Copyright (C) 2015-2018 0nse, Andreas Shimokawa, Carsten Pfeiffer,
Daniele Gobbetti, João Paulo Barraca, ladbsoft, protomors, Quallenauge,
Sami Alaoui, Sergey Trofimov, tiparega
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;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.widget.Toast;
import java.lang.reflect.Constructor;
import java.util.EnumSet;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor.AmazfitCorSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband3.MiBand3Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband2.MiBand2Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.no1f1.No1F1Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.vibratissimo.VibratissimoSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30Support;
<<<<<<< HEAD
import nodomain.freeyourgadget.gadgetbridge.service.devices.zetime.ZeTimeDeviceSupport;
=======
import nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch.XWatchSupport;
>>>>>>> master
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class DeviceSupportFactory {
private final BluetoothAdapter mBtAdapter;
private final Context mContext;
public DeviceSupportFactory(Context context) {
mContext = context;
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
}
public synchronized DeviceSupport createDeviceSupport(GBDevice device) throws GBException {
DeviceSupport deviceSupport = null;
String deviceAddress = device.getAddress();
int indexFirstColon = deviceAddress.indexOf(":");
if (indexFirstColon > 0) {
if (indexFirstColon == deviceAddress.lastIndexOf(":")) { // only one colon
deviceSupport = createTCPDeviceSupport(device);
} else {
// multiple colons -- bt?
deviceSupport = createBTDeviceSupport(device);
}
} else {
// no colon at all, maybe a class name?
deviceSupport = createClassNameDeviceSupport(device);
}
if (deviceSupport != null) {
return deviceSupport;
}
// no device found, check transport availability and warn
checkBtAvailability();
return null;
}
private DeviceSupport createClassNameDeviceSupport(GBDevice device) throws GBException {
String className = device.getAddress();
try {
Class<?> deviceSupportClass = Class.forName(className);
Constructor<?> constructor = deviceSupportClass.getConstructor();
DeviceSupport support = (DeviceSupport) constructor.newInstance();
// has to create the device itself
support.setContext(device, null, mContext);
return support;
} catch (ClassNotFoundException e) {
return null; // not a class, or not known at least
} catch (Exception e) {
throw new GBException("Error creating DeviceSupport instance for " + className, e);
}
}
private void checkBtAvailability() {
if (mBtAdapter == null) {
GB.toast(mContext.getString(R.string.bluetooth_is_not_supported_), Toast.LENGTH_SHORT, GB.WARN);
} else if (!mBtAdapter.isEnabled()) {
GB.toast(mContext.getString(R.string.bluetooth_is_disabled_), Toast.LENGTH_SHORT, GB.WARN);
}
}
private DeviceSupport createBTDeviceSupport(GBDevice gbDevice) throws GBException {
if (mBtAdapter != null && mBtAdapter.isEnabled()) {
DeviceSupport deviceSupport = null;
try {
switch (gbDevice.getType()) {
case PEBBLE:
deviceSupport = new ServiceDeviceSupport(new PebbleSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case MIBAND:
deviceSupport = new ServiceDeviceSupport(new MiBandSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case MIBAND2:
deviceSupport = new ServiceDeviceSupport(new MiBand2Support(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case MIBAND3:
deviceSupport = new ServiceDeviceSupport(new MiBand3Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case AMAZFITBIP:
deviceSupport = new ServiceDeviceSupport(new AmazfitBipSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case AMAZFITCOR:
deviceSupport = new ServiceDeviceSupport(new AmazfitCorSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case VIBRATISSIMO:
deviceSupport = new ServiceDeviceSupport(new VibratissimoSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case LIVEVIEW:
deviceSupport = new ServiceDeviceSupport(new LiveviewSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case HPLUS:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.HPLUS), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case MAKIBESF68:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.MAKIBESF68), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case EXRIZUK8:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.EXRIZUK8), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case Q8:
deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.Q8), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case NO1F1:
deviceSupport = new ServiceDeviceSupport(new No1F1Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
case TECLASTH30:
deviceSupport = new ServiceDeviceSupport(new TeclastH30Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
<<<<<<< HEAD
case ZETIME:
deviceSupport = new ServiceDeviceSupport(new ZeTimeDeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
=======
case XWATCH:
deviceSupport = new ServiceDeviceSupport(new XWatchSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
>>>>>>> master
}
if (deviceSupport != null) {
deviceSupport.setContext(gbDevice, mBtAdapter, mContext);
return deviceSupport;
}
} catch (Exception e) {
throw new GBException(mContext.getString(R.string.cannot_connect_bt_address_invalid_), e);
}
}
return null;
}
private DeviceSupport createTCPDeviceSupport(GBDevice gbDevice) throws GBException {
try {
DeviceSupport deviceSupport = new ServiceDeviceSupport(new PebbleSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
deviceSupport.setContext(gbDevice, mBtAdapter, mContext);
return deviceSupport;
} catch (Exception e) {
throw new GBException("cannot connect to " + gbDevice, e); // FIXME: localize
}
}
}

View File

@ -170,7 +170,7 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport {
} }
@Override @Override
public void onFetchActivityData() { public void onFetchRecordedData(int dataTypes) {
try { try {
TransactionBuilder builder = performInitialized("fetchActivityData"); TransactionBuilder builder = performInitialized("fetchActivityData");
requestActivityInfo(builder); requestActivityInfo(builder);
@ -515,15 +515,15 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport {
provider.addGBActivitySample(sample); provider.addGBActivitySample(sample);
} catch (Exception ex) { } catch (Exception ex) {
GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
GB.updateTransferNotification("Data transfer failed", false, 0, getContext()); GB.updateTransferNotification(null,"Data transfer failed", false, 0, getContext());
} }
progressSteps = msg[5] + msg[6] * 256; progressSteps = msg[5] + msg[6] * 256;
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableStepsData), getContext()); GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableStepsData), getContext());
if (progressSteps == availableStepsData) { if (progressSteps == availableStepsData) {
progressSteps = 0; progressSteps = 0;
availableStepsData = 0; availableStepsData = 0;
GB.updateTransferNotification("", false, 100, getContext()); GB.updateTransferNotification(null,"", false, 100, getContext());
if (getDevice().isBusy()) { if (getDevice().isBusy()) {
getDevice().unsetBusyTask(); getDevice().unsetBusyTask();
getDevice().sendDeviceUpdateIntent(getContext()); getDevice().sendDeviceUpdateIntent(getContext());
@ -558,15 +558,15 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport {
provider.addGBActivitySample(sample); provider.addGBActivitySample(sample);
} catch (Exception ex) { } catch (Exception ex) {
GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
GB.updateTransferNotification("Data transfer failed", false, 0, getContext()); GB.updateTransferNotification(null,"Data transfer failed", false, 0, getContext());
} }
progressSteps = msg[5] + msg[6] * 256; progressSteps = msg[5] + msg[6] * 256;
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableSleepData), getContext()); GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableSleepData), getContext());
if (progressSteps == availableStepsData) { if (progressSteps == availableStepsData) {
progressSteps = 0; progressSteps = 0;
availableSleepData = 0; availableSleepData = 0;
GB.updateTransferNotification("", false, 100, getContext()); GB.updateTransferNotification(null,"", false, 100, getContext());
if (getDevice().isBusy()) { if (getDevice().isBusy()) {
getDevice().unsetBusyTask(); getDevice().unsetBusyTask();
getDevice().sendDeviceUpdateIntent(getContext()); getDevice().sendDeviceUpdateIntent(getContext());
@ -587,15 +587,15 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport {
provider.addGBActivitySample(sample); provider.addGBActivitySample(sample);
} catch (Exception ex) { } catch (Exception ex) {
GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); GB.toast(getContext(), "Error saving steps data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
GB.updateTransferNotification("Data transfer failed", false, 0, getContext()); GB.updateTransferNotification(null,"Data transfer failed", false, 0, getContext());
} }
progressSteps = msg[5] + msg[6] * 256; progressSteps = msg[5] + msg[6] * 256;
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableHeartRateData), getContext()); GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (progressSteps *100 / availableHeartRateData), getContext());
if (progressSteps == availableStepsData) { if (progressSteps == availableStepsData) {
progressSteps = 0; progressSteps = 0;
availableHeartRateData = 0; availableHeartRateData = 0;
GB.updateTransferNotification("", false, 100, getContext()); GB.updateTransferNotification(null,"", false, 100, getContext());
if (getDevice().isBusy()) { if (getDevice().isBusy()) {
getDevice().unsetBusyTask(); getDevice().unsetBusyTask();
getDevice().sendDeviceUpdateIntent(getContext()); getDevice().sendDeviceUpdateIntent(getContext());

View File

@ -1,311 +0,0 @@
/* Copyright (C) 2015-2018 0nse, Andreas Shimokawa, Carsten Pfeiffer,
Daniele Gobbetti, João Paulo Barraca, ladbsoft, protomors, Quallenauge,
Sami Alaoui, tiparega
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 android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.support.annotation.NonNull;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
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.hplus.Q8Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor.AmazfitCorCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2HRXCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband3.MiBand3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;
<<<<<<< HEAD
import nodomain.freeyourgadget.gadgetbridge.devices.zetime.ZeTimeCoordinator;
=======
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchCoordinator;
>>>>>>> master
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class DeviceHelper {
private static final Logger LOG = LoggerFactory.getLogger(DeviceHelper.class);
private static final DeviceHelper instance = new DeviceHelper();
public static DeviceHelper getInstance() {
return instance;
}
// lazily created
private List<DeviceCoordinator> coordinators;
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
for (DeviceCoordinator coordinator : getAllCoordinators()) {
DeviceType deviceType = coordinator.getSupportedType(candidate);
if (deviceType.isSupported()) {
return deviceType;
}
}
return DeviceType.UNKNOWN;
}
public boolean getSupportedType(GBDevice device) {
for (DeviceCoordinator coordinator : getAllCoordinators()) {
if (coordinator.supports(device)) {
return true;
}
}
return false;
}
public GBDevice findAvailableDevice(String deviceAddress, Context context) {
Set<GBDevice> availableDevices = getAvailableDevices(context);
for (GBDevice availableDevice : availableDevices) {
if (deviceAddress.equals(availableDevice.getAddress())) {
return availableDevice;
}
}
return null;
}
/**
* Returns the list of all available devices that are supported by Gadgetbridge.
* Note that no state is known about the returned devices. Even if one of those
* devices is connected, it will report the default not-connected state.
*
* Clients interested in the "live" devices being managed should use the class
* DeviceManager.
* @param context
* @return
*/
public Set<GBDevice> getAvailableDevices(Context context) {
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<GBDevice> availableDevices = new LinkedHashSet<GBDevice>();
if (btAdapter == null) {
GB.toast(context, context.getString(R.string.bluetooth_is_not_supported_), Toast.LENGTH_SHORT, GB.WARN);
} else if (!btAdapter.isEnabled()) {
GB.toast(context, context.getString(R.string.bluetooth_is_disabled_), Toast.LENGTH_SHORT, GB.WARN);
}
List<GBDevice> dbDevices = getDatabaseDevices();
// these come first, as they have the most information already
availableDevices.addAll(dbDevices);
if (btAdapter != null) {
List<GBDevice> bondedDevices = getBondedDevices(btAdapter);
availableDevices.addAll(bondedDevices);
}
Prefs prefs = GBApplication.getPrefs();
String miAddr = prefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
if (miAddr.length() > 0) {
GBDevice miDevice = new GBDevice(miAddr, "MI", DeviceType.MIBAND);
availableDevices.add(miDevice);
}
String pebbleEmuAddr = prefs.getString("pebble_emu_addr", "");
String pebbleEmuPort = prefs.getString("pebble_emu_port", "");
if (pebbleEmuAddr.length() >= 7 && pebbleEmuPort.length() > 0) {
GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", DeviceType.PEBBLE);
availableDevices.add(pebbleEmuDevice);
}
return availableDevices;
}
public GBDevice toSupportedDevice(BluetoothDevice device) {
GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN, device.getUuids());
return toSupportedDevice(candidate);
}
public GBDevice toSupportedDevice(GBDeviceCandidate candidate) {
for (DeviceCoordinator coordinator : getAllCoordinators()) {
if (coordinator.supports(candidate)) {
return coordinator.createDevice(candidate);
}
}
return null;
}
public DeviceCoordinator getCoordinator(GBDeviceCandidate device) {
synchronized (this) {
for (DeviceCoordinator coord : getAllCoordinators()) {
if (coord.supports(device)) {
return coord;
}
}
}
return new UnknownDeviceCoordinator();
}
public DeviceCoordinator getCoordinator(GBDevice device) {
synchronized (this) {
for (DeviceCoordinator coord : getAllCoordinators()) {
if (coord.supports(device)) {
return coord;
}
}
}
return new UnknownDeviceCoordinator();
}
public synchronized List<DeviceCoordinator> getAllCoordinators() {
if (coordinators == null) {
coordinators = createCoordinators();
}
return coordinators;
}
private List<DeviceCoordinator> createCoordinators() {
List<DeviceCoordinator> result = new ArrayList<>();
result.add(new AmazfitBipCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new AmazfitCorCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand3Coordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand2HRXCoordinator()); // Note: must come before MiBand2 because detection is hacky, atm
result.add(new MiBand2Coordinator()); // Note: MiBand2 must come before MiBand because detection is hacky, atm
result.add(new MiBandCoordinator());
result.add(new PebbleCoordinator());
result.add(new VibratissimoCoordinator());
result.add(new LiveviewCoordinator());
result.add(new HPlusCoordinator());
result.add(new No1F1Coordinator());
result.add(new MakibesF68Coordinator());
result.add(new Q8Coordinator());
result.add(new EXRIZUK8Coordinator());
result.add(new TeclastH30Coordinator());
<<<<<<< HEAD
result.add(new ZeTimeCoordinator());
=======
result.add(new XWatchCoordinator());
>>>>>>> master
return result;
}
private List<GBDevice> getDatabaseDevices() {
List<GBDevice> result = new ArrayList<>();
try (DBHandler lockHandler = GBApplication.acquireDB()) {
List<Device> activeDevices = DBHelper.getActiveDevices(lockHandler.getDaoSession());
for (Device dbDevice : activeDevices) {
GBDevice gbDevice = toGBDevice(dbDevice);
if (gbDevice != null && DeviceHelper.getInstance().getSupportedType(gbDevice)) {
result.add(gbDevice);
}
}
return result;
} catch (Exception e) {
GB.toast("Error retrieving devices from database", Toast.LENGTH_SHORT, GB.ERROR);
return Collections.emptyList();
}
}
/**
* Converts a known device from the database to a GBDevice.
* Note: The device might not be supported anymore, so callers should verify that.
* @param dbDevice
* @return
*/
public GBDevice toGBDevice(Device dbDevice) {
DeviceType deviceType = DeviceType.fromKey(dbDevice.getType());
GBDevice gbDevice = new GBDevice(dbDevice.getIdentifier(), dbDevice.getName(), deviceType);
List<DeviceAttributes> deviceAttributesList = dbDevice.getDeviceAttributesList();
if (deviceAttributesList.size() > 0) {
gbDevice.setModel(dbDevice.getModel());
DeviceAttributes attrs = deviceAttributesList.get(0);
gbDevice.setFirmwareVersion(attrs.getFirmwareVersion1());
gbDevice.setFirmwareVersion2(attrs.getFirmwareVersion2());
gbDevice.setVolatileAddress(attrs.getVolatileIdentifier());
}
return gbDevice;
}
private @NonNull List<GBDevice> getBondedDevices(@NonNull BluetoothAdapter btAdapter) {
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices == null) {
return Collections.emptyList();
}
List<GBDevice> result = new ArrayList<>(pairedDevices.size());
DeviceHelper deviceHelper = DeviceHelper.getInstance();
for (BluetoothDevice pairedDevice : pairedDevices) {
if (pairedDevice == null) {
continue; // just to be safe, see https://github.com/Freeyourgadget/Gadgetbridge/pull/1052
}
if (pairedDevice.getName() != null && (pairedDevice.getName().startsWith("Pebble-LE ") || pairedDevice.getName().startsWith("Pebble Time LE "))) {
continue; // ignore LE Pebble (this is part of the main device now (volatileAddress)
}
GBDevice device = deviceHelper.toSupportedDevice(pairedDevice);
if (device != null) {
result.add(device);
}
}
return result;
}
/**
* Attempts to removing the bonding with the given device. Returns true
* if bonding was supposedly successful and false if anything went wrong
* @param device
* @return
*/
public boolean removeBond(GBDevice device) throws GBException {
BluetoothAdapter defaultAdapter = BluetoothAdapter.getDefaultAdapter();
if (defaultAdapter != null) {
BluetoothDevice remoteDevice = defaultAdapter.getRemoteDevice(device.getAddress());
if (remoteDevice != null) {
try {
Method method = BluetoothDevice.class.getMethod("removeBond", (Class[]) null);
Object result = method.invoke(remoteDevice, (Object[]) null);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
throw new GBException("Error removing bond to device: " + device, e);
}
}
}
return false;
}
}

View File

@ -1,585 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">Gadgetbridge</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="action_settings">Settings</string>
<string name="action_debug">Debug</string>
<string name="action_quit">Quit</string>
<string name="action_donate">Donate</string>
<string name="controlcenter_fetch_activity_data">Synchronize</string>
<string name="controlcenter_find_device">Find lost Device</string>
<string name="controlcenter_take_screenshot">Take Screenshot</string>
<string name="controlcenter_connect">Connect</string>
<string name="controlcenter_disconnect">Disconnect</string>
<string name="controlcenter_delete_device">Delete Device</string>
<string name="controlcenter_delete_device_name">Delete %1$s</string>
<string name="controlcenter_delete_device_dialogmessage">This will delete the device and all associated data!</string>
<string name="controlcenter_navigation_drawer_open">Open navigation drawer</string>
<string name="controlcenter_navigation_drawer_close">Close navigation drawer</string>
<string name="controlcenter_snackbar_need_longpress">Long press the card to disconnect</string>
<string name="controlcenter_snackbar_disconnecting">Disconnecting</string>
<string name="controlcenter_snackbar_connecting">Connecting</string>
<string name="controlcenter_snackbar_requested_screenshot">Taking a screenshot of the device</string>
<string name="title_activity_debug">Debug</string>
<!-- Strings related to AppManager -->
<string name="title_activity_appmanager">App Manager</string>
<string name="appmanager_cached_watchapps_watchfaces">Apps in cache</string>
<string name="appmanager_installed_watchapps">Installed apps</string>
<string name="appmanager_installed_watchfaces">Installed watchfaces</string>
<string name="appmananger_app_delete">Delete</string>
<string name="appmananger_app_delete_cache">Delete and remove from cache</string>
<string name="appmananger_app_reinstall">Reinstall</string>
<string name="appmanager_app_openinstore">Search in Pebble appstore</string>
<string name="appmanager_health_activate">Activate</string>
<string name="appmanager_health_deactivate">Deactivate</string>
<string name="appmanager_hrm_activate">Activate HRM</string>
<string name="appmanager_hrm_deactivate">Deactivate HRM</string>
<string name="appmanager_weather_activate">Activate system weather app</string>
<string name="appmanager_weather_deactivate">Deactivate system weather app</string>
<string name="appmanager_weather_install_provider">Install the weather notification app</string>
<string name="app_configure">Configure</string>
<string name="app_move_to_top">Move to top</string>
<!-- Strings related to AppBlacklist -->
<string name="title_activity_appblacklist">Notification blacklist</string>
<string name="blacklist_all_for_notifications">Blacklist all for notifications</string>
<string name="whitelist_all_for_notifications">Whitelist all for notifications</string>
<!-- Strings related to CalBlacklist -->
<string name="title_activity_calblacklist">Blacklisted Calendars</string>
<!-- Strings related to FwAppInstaller -->
<string name="title_activity_fw_app_insaller">FW/App installer</string>
<string name="fw_upgrade_notice">You are about to install firmware %s instead of the one currently on your Mi Band.</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="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 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="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 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\nUNTESTED, MAY BRICK YOUR DEVICE, PROCEED AT YOUR OWN RISK!</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="miband_firmware_known">This firmware has been tested and is known to be compatible with Gadgetbridge.</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 onto your Mi Band!"</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>
<!-- Strings related to Settings -->
<string name="title_activity_settings">Settings</string>
<string name="pref_header_general">General settings</string>
<string name="pref_title_general_autoconnectonbluetooth">Connect to device when Bluetooth turned on</string>
<string name="pref_title_general_autostartonboot">Start automatically</string>
<string name="pref_title_general_autoreconnect">Reconnect automatically</string>
<string name="pref_title_audio_player">Preferred Audioplayer</string>
<string name="pref_default">Default</string>
<string name="pref_title_charts_swipe">Enable left/right swipe in the charts activity</string>
<string name="pref_header_datetime">Date and Time</string>
<string name="pref_title_datetime_syctimeonconnect">Sync time</string>
<string name="pref_summary_datetime_syctimeonconnect">Sync time to device when connecting, and when time or time zone changes on Android</string>
<string name="pref_title_theme">Theme</string>
<string name="pref_theme_light">Light</string>
<string name="pref_theme_dark">Dark</string>
<string name="pref_title_language">Language</string>
<string name="pref_title_minimize_priority">Hide the Gadgetbridge notification</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_summary_minimize_priority_on">The icon in the status bar and the notification in the lockscreen are hidden</string>
<string name="pref_header_notifications">Notifications</string>
<string name="pref_title_notifications_repetitions">Repetitions</string>
<string name="pref_title_notifications_call">Phone Calls</string>
<string name="pref_title_notifications_sms">SMS</string>
<string name="pref_title_notifications_pebblemsg">Pebble Messages</string>
<string name="pref_summary_notifications_pebblemsg">Support for applications which send notifications to the Pebble via PebbleKit.</string>
<string name="pref_title_notifications_generic">Generic notification support</string>
<string name="pref_title_whenscreenon">…also when screen is on</string>
<string name="pref_title_notification_filter">Do Not Disturb</string>
<string name="pref_summary_notification_filter">Stop unwanted notifications from being sent in Do Not Disturb mode</string>
<string name="pref_title_transliteration">Transliteration</string>
<string name="pref_summary_transliteration">Enable this if your device has no support for your language\'s font</string>
<string name="always">Always</string>
<string name="when_screen_off">When screen is off</string>
<string name="never">Never</string>
<string name="pref_header_privacy">Privacy</string>
<string name="pref_title_call_privacy_mode">Call privacy mode</string>
<string name="pref_call_privacy_mode_off">Display name and number</string>
<string name="pref_call_privacy_mode_name">Hide name but display number</string>
<string name="pref_call_privacy_mode_number">Hide number but display name</string>
<string name="pref_call_privacy_mode_complete">Hide name and number</string>
<string name="pref_title_weather">Weather</string>
<string name="pref_title_weather_location">Weather location (CM/LOS)</string>
<string name="pref_blacklist">Blacklist Apps</string>
<string name="pref_blacklist_calendars">Blacklist Calendars</string>
<string name="pref_header_cannned_messages">Canned messages</string>
<string name="pref_title_canned_replies">Replies</string>
<string name="pref_title_canned_reply_suffix">Common suffix</string>
<string name="pref_title_canned_messages_dismisscall">Call Dismissal</string>
<string name="pref_title_canned_messages_set">Update on Pebble</string>
<string name="pref_header_development">Developer options</string>
<string name="pref_title_development_miaddr">Mi Band address</string>
<string name="pref_title_pebble_settings">Pebble settings</string>
<string name="pref_header_activitytrackers">Activity trackers</string>
<string name="pref_title_pebble_activitytracker">Preferred activity tracker</string>
<string name="pref_title_pebble_sync_health">Sync Pebble Health</string>
<string name="pref_title_pebble_sync_misfit">Sync Misfit</string>
<string name="pref_title_pebble_sync_morpheuz">Sync Morpheuz</string>
<string name="pref_title_enable_outgoing_call">Support outgoing calls</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_pebblekit">Allow 3rd party Android App access</string>
<string name="pref_summary_enable_pebblekit">Enable experimental support for Android Apps using PebbleKit</string>
<string name="pref_header_pebble_timeline">Pebble timeline</string>
<string name="pref_title_sunrise_sunset">Sunrise and sunset</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_enable_calendar_sync">Sync calendar</string>
<string name="pref_summary_enable_calendar_sync">Send calendar events to the timeline</string>
<string name="pref_title_autoremove_notifications">Autoremove dismissed notifications</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_pebble_privacy_mode">Privacy mode</string>
<string name="pref_pebble_privacy_mode_off">Normal notifications</string>
<string name="pref_pebble_privacy_mode_content">Shift the notification text off-screen</string>
<string name="pref_pebble_privacy_mode_complete">Show only the notification icon</string>
<string name="pref_header_location">Location</string>
<string name="pref_title_location_aquire">Acquire location</string>
<string name="pref_title_location_latitude">Latitude</string>
<string name="pref_title_location_longitude">Longitude</string>
<string name="pref_title_location_keep_uptodate">Keep location updated</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="toast_enable_networklocationprovider">Please enable network location</string>
<string name="toast_aqurired_networklocation">location acquired</string>
<string name="pref_title_pebble_forceprotocol">Force notification protocol</string>
<string name="pref_summary_pebble_forceprotocol">This option forces using the latest notification protocol depending on the firmware version. ENABLE ONLY IF YOU KNOW WHAT YOU ARE DOING!</string>
<string name="pref_title_pebble_forceuntested">Enable untested features</string>
<string name="pref_summary_pebble_forceuntested">Enable features that are untested. ENABLE ONLY IF YOU KNOW WHAT YOU ARE DOING!</string>
<string name="pref_title_pebble_forcele">Always prefer BLE</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_mtu_limit">Pebble 2/LE GATT MTU limit</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_gatt_clientonly">GATT client only</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_enable_applogs">Enable watch App logging</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_always_ack_pebblekit">Prematurely ACK PebbleKit</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_enable_bgjs">Enable background JS</string>
<string name="pref_summary_pebble_enable_bgjs">When enabled, allows watchfaces to show weather, battery info etc.</string>
<string name="pref_title_pebble_reconnect_attempts">Reconnection attempts</string>
<!-- HPlus Preferences -->
<string name="pref_title_unit_system">Units</string>
<string name="pref_title_timeformat">Time format</string>
<string name="pref_title_screentime">Screen on duration</string>
<string name="prefs_title_all_day_heart_rate">All day heart rate measurement</string>
<string name="preferences_hplus_settings">HPlus/Makibes settings</string>
<!-- Auto export preferences -->
<string name="pref_header_auto_export">Auto export</string>
<string name="pref_title_auto_export_enabled">Auto export enabled</string>
<string name="pref_title_auto_export_location">Export location</string>
<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_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="not_connected">Not connected</string>
<string name="connecting">Connecting</string>
<string name="connected">Connected</string>
<string name="unknown_state">Unknown state</string>
<string name="_unknown_">(unknown)</string>
<string name="test">Test</string>
<string name="test_notification">Test notification</string>
<string name="this_is_a_test_notification_from_gadgetbridge">This is a test notification from Gadgetbridge</string>
<string name="bluetooth_is_not_supported_">Bluetooth is not supported.</string>
<string name="bluetooth_is_disabled_">Bluetooth is disabled.</string>
<string name="tap_connected_device_for_app_mananger">Tap connected device for App manager</string>
<string name="tap_connected_device_for_activity">Tap connected device for activity</string>
<string name="tap_connected_device_for_vibration">Tap connected device for vibration</string>
<string name="tap_a_device_to_connect">Tap a device to connect</string>
<string name="cannot_connect_bt_address_invalid_">Cannot connect. Bluetooth address invalid?</string>
<string name="gadgetbridge_running">Gadgetbridge running</string>
<string name="installing_binary_d_d">Installing binary %1$d/%2$d</string>
<string name="installation_failed_">Installation failed</string>
<string name="installation_successful">Installed</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="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="n_a">N/A</string>
<string name="initialized">initialized</string>
<string name="appversion_by_creator">%1$s by %2$s</string>
<string name="title_activity_discovery">Device discovery</string>
<string name="discovery_stop_scanning">Stop scanning</string>
<string name="discovery_start_scanning">Start discovery</string>
<string name="action_discover">Connect new device</string>
<string name="device_with_rssi">%1$s (%2$s)</string>
<string name="title_activity_android_pairing">Pair device</string>
<string name="android_pairing_hint">Use the Android Bluetooth pairing dialog to pair the device.</string>
<string name="title_activity_mi_band_pairing">Pair your Mi Band</string>
<string name="pairing">Pairing with %s…</string>
<string name="pairing_creating_bond_with">"Creating bond with %1$s (%2$s)"</string>
<string name="pairing_unable_to_pair_with">"Unable to pair with %1$s (%2$s)"</string>
<string name="pairing_in_progress">Bonding in progress: %1$s (%2$s)</string>
<string name="pairing_already_bonded">"Already bonded with %1$s (%2$s), connecting…"</string>
<string name="message_cannot_pair_no_mac">No MAC address passed, cannot pair.</string>
<string name="preferences_category_device_specific_settings">Device specific settings</string>
<string name="preferences_miband_settings">Mi Band / Amazfit settings</string>
<string name="preferences_amazfitbip_settings">Amazfit Bip settings</string>
<string name="male">Male</string>
<string name="female">Female</string>
<string name="other">Other</string>
<string name="left">Left</string>
<string name="right">Right</string>
<string name="miband_pairing_using_dummy_userdata">No valid user data given, using dummy user data for now.</string>
<string name="miband_pairing_tap_hint">When your Mi Band vibrates and blinks, tap it a few times in a row.</string>
<string name="appinstaller_install">Install</string>
<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="discovery_note">Note:</string>
<string name="candidate_item_device_image">Device image</string>
<string name="miband_prefs_alias">Name/Alias</string>
<string name="pref_header_vibration_count">Vibration count</string>
<string name="title_activity_sleepmonitor">Sleep monitor</string>
<string name="pref_write_logfiles">Write log files</string>
<string name="initializing">Initializing</string>
<string name="busy_task_fetch_activity_data">Fetching activity data</string>
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
<string name="miband_prefs_wearside">Wearing left or right?</string>
<string name="pref_screen_vibration_profile">Vibration profile</string>
<string name="vibration_profile_staccato">Staccato</string>
<string name="vibration_profile_short">Short</string>
<string name="vibration_profile_medium">Medium</string>
<string name="vibration_profile_long">Long</string>
<string name="vibration_profile_waterdrop">Waterdrop</string>
<string name="vibration_profile_ring">Ring</string>
<string name="vibration_profile_alarm_clock">Alarm clock</string>
<string name="miband_prefs_vibration">Vibration</string>
<string name="vibration_try">Try</string>
<string name="pref_screen_notification_profile_sms">SMS notification</string>
<string name="pref_header_vibration_settings">Vibration settings</string>
<string name="pref_screen_notification_profile_generic">Generic notification</string>
<string name="pref_screen_notification_profile_email">Email notification</string>
<string name="pref_screen_notification_profile_incoming_call">Incoming call notification</string>
<string name="pref_screen_notification_profile_generic_chat">Chat</string>
<string name="pref_screen_notification_profile_generic_navigation">Navigation</string>
<string name="pref_screen_notification_profile_generic_social">Social network</string>
<string name="prefs_title_heartrate_measurement_interval">Whole day HR measurement</string>
<string name="interval_one_minute">once a minute</string>
<string name="interval_five_minutes">every 5 minutes</string>
<string name="interval_ten_minutes">every 10 minutes</string>
<string name="interval_thirty_minutes">every 30 minutes</string>
<string name="interval_one_hour">once an hour</string>
<string name="stats_title">Speed zones</string>
<string name="stats_x_axis_label">Total minutes</string>
<string name="stats_y_axis_label">Steps per minute</string>
<string name="control_center_find_lost_device">Find lost device</string>
<string name="control_center_cancel_to_stop_vibration">Cancel to stop vibration.</string>
<string name="title_activity_charts">Your activity</string>
<string name="title_activity_set_alarm">Configure alarms</string>
<string name="controlcenter_start_configure_alarms">Configure alarms</string>
<string name="title_activity_alarm_details">Alarm details</string>
<string name="alarm_sun_short">Sun</string>
<string name="alarm_mon_short">Mon</string>
<string name="alarm_tue_short">Tue</string>
<string name="alarm_wed_short">Wed</string>
<string name="alarm_thu_short">Thu</string>
<string name="alarm_fri_short">Fri</string>
<string name="alarm_sat_short">Sat</string>
<string name="alarm_smart_wakeup">Smart wakeup</string>
<string name="user_feedback_miband_set_alarms_failed">There was an error setting the alarms, please try again!</string>
<string name="user_feedback_miband_set_alarms_ok">Alarms sent to device!</string>
<string name="chart_no_data_synchronize">No data. Synchronize device?</string>
<string name="user_feedback_miband_activity_data_transfer">About to transfer %1$s of data starting from %2$s</string>
<string name="miband_prefs_fitness_goal">Daily step target</string>
<string name="dbaccess_error_executing">Error executing \'%1$s\'</string>
<string name="controlcenter_start_activitymonitor">Your activity (ALPHA)</string>
<string name="cannot_connect">Cannot connect: %1$s</string>
<string name="installer_activity_unable_to_find_handler">Unable to find a handler to install this file.</string>
<string name="pbw_install_handler_unable_to_install">Unable to install the given file: %1$s</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="installer_activity_wait_while_determining_status">Please wait while determining the installation status…</string>
<string name="notif_battery_low_title">Gadget battery Low!</string>
<string name="notif_battery_low_percent">%1$s battery left: %2$s%%</string>
<string name="notif_battery_low_bigtext_last_charge_time">Last charge: %s \n</string>
<string name="notif_battery_low_bigtext_number_of_charges">Number of charges: %s</string>
<string name="notif_export_failed_title">Export database failed! Please check your settings.</string>
<string name="sleepchart_your_sleep">Your sleep</string>
<string name="weeksleepchart_sleep_a_week">Sleep per week</string>
<string name="weeksleepchart_today_sleep_description">Sleep today, target: %1$s</string>
<string name="weekstepschart_steps_a_week">Steps per week</string>
<string name="activity_sleepchart_activity_and_sleep">Your activity and sleep</string>
<string name="updating_firmware">Flashing firmware…</string>
<string name="fwapp_install_device_not_ready">File cannot be installed, device not ready.</string>
<string name="installhandler_firmware_name">%1$s: %2$s %3$s</string>
<string name="miband_fwinstaller_compatible_version">Compatible version</string>
<string name="miband_fwinstaller_untested_version">Untested version!</string>
<string name="fwappinstaller_connection_state">Connection to device: %1$s</string>
<string name="pbw_installhandler_pebble_firmware">Pebble Firmware %1$s</string>
<string name="pbwinstallhandler_correct_hw_revision">Correct hardware revision</string>
<string name="pbwinstallhandler_incorrect_hw_revision">Hardware revision mismatch!</string>
<string name="pbwinstallhandler_app_item">%1$s (%2$s)</string>
<string name="updatefirmwareoperation_updateproblem_do_not_reboot">Problem with the firmware transfer. DO NOT REBOOT your Mi Band!</string>
<string name="updatefirmwareoperation_metadata_updateproblem">Problem with the firmware metadata transfer</string>
<string name="updatefirmwareoperation_update_complete">Firmware installation complete</string>
<string name="updatefirmwareoperation_update_complete_rebooting">Firmware installation complete, rebooting device…</string>
<string name="updatefirmwareoperation_write_failed">Firmware flashing failed</string>
<string name="chart_steps">Steps</string>
<string name="calories">Calories</string>
<string name="distance">Distance</string>
<string name="clock">Clock</string>
<string name="heart_rate">Heart rate</string>
<string name="battery">Battery</string>
<string name="liveactivity_live_activity">Live activity</string>
<string name="weeksteps_today_steps_description">Steps today, target: %1$s</string>
<string name="pref_title_dont_ack_transfer">Do not ACK activity data transfer</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_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_title_low_latency_fw_update">Use low-latency mode for firmware flashing</string>
<string name="pref_summary_low_latency_fw_update">This might help on devices where firmware flashing fails</string>
<string name="live_activity_steps_history">Steps history</string>
<string name="live_activity_current_steps_per_minute">Current steps/min</string>
<string name="live_activity_total_steps">Total steps</string>
<string name="live_activity_steps_per_minute_history">Steps per minute history</string>
<string name="live_activity_start_your_activity">Start your activity</string>
<string name="abstract_chart_fragment_kind_activity">Activity</string>
<string name="abstract_chart_fragment_kind_light_sleep">Light sleep</string>
<string name="abstract_chart_fragment_kind_deep_sleep">Deep sleep</string>
<string name="abstract_chart_fragment_kind_not_worn">Not worn</string>
<string name="device_not_connected">Not connected.</string>
<string name="user_feedback_all_alarms_disabled">All alarms disabled</string>
<string name="pref_title_keep_data_on_device">Keep activity data on device</string>
<string name="miband_fwinstaller_incompatible_version">Incompatible firmware</string>
<string name="fwinstaller_firmware_not_compatible_to_device">This firmware is not compatible with the device</string>
<string name="miband_prefs_reserve_alarm_calendar">Alarms to reserve for upcoming events</string>
<string name="miband_prefs_hr_sleep_detection">Use heart rate sensor to improve sleep detection</string>
<string name="miband_prefs_device_time_offset_hours">Device time offset in hours (for detecting sleep of shift workers)</string>
<string name="miband2_prefs_dateformat">Mi2: Date format</string>
<string name="dateformat_time">Time</string>
<string name="dateformat_date_time"><![CDATA[Time & date]]></string>
<string name="mi2_prefs_button_actions">Button actions</string>
<string name="mi2_prefs_button_actions_summary">Specify actions on Mi Band 2 button press</string>
<string name="mi2_prefs_button_press_count">Button press count</string>
<string name="mi2_prefs_button_press_count_summary">Number of button presses to trigger message broadcast</string>
<string name="mi2_prefs_button_press_broadcast">Broadcast message to send</string>
<string name="mi2_prefs_button_press_broadcast_summary">Broadcast message on defined number of button presses reached</string>
<string name="mi2_prefs_button_press_broadcast_default_value" translatable="false">nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed</string>
<string name="mi2_prefs_button_action">Enable button action</string>
<string name="mi2_prefs_button_action_summary">Enable action on specified number of button presses</string>
<string name="mi2_prefs_button_action_vibrate">Enable band vibration</string>
<string name="mi2_prefs_button_action_vibrate_summary">Enable band vibration on button action triggered</string>
<string name="mi2_prefs_button_press_count_max_delay">Maximum delay between presses</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_match_delay">Delay after button action</string>
<string name="mi2_prefs_button_press_count_match_delay_summary">Delay after one button action match (number is in button_id intent extra) or 0 for immediately</string>
<string name="mi2_prefs_goal_notification">Goal notification</string>
<string name="mi2_prefs_goal_notification_summary">The band will vibrate when the daily steps goal is reached</string>
<string name="mi2_prefs_display_items">Display items</string>
<string name="mi2_prefs_display_items_summary">Choose the items displayed on the band screen</string>
<string name="mi2_prefs_activate_display_on_lift">Activate display upon lift</string>
<string name="mi2_prefs_rotate_wrist_to_switch_info">Rotate wrist to switch info</string>
<string name="mi2_prefs_do_not_disturb">Do Not Disturb</string>
<string name="mi2_prefs_do_not_disturb_summary">The band won\'t receive notifications while active</string>
<string name="mi2_prefs_inactivity_warnings">Inactivity warnings</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_threshold">Inactivity threshold (in minutes)</string>
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Disable the inactivity warnings for a time interval</string>
<string name="mi2_prefs_do_not_disturb_start">Start time</string>
<string name="mi2_prefs_do_not_disturb_end">End time</string>
<string name="automatic">Automatic</string>
<string name="simplified_chinese">Simplified Chinese</string>
<string name="traditional_chinese">Traditional Chinese</string>
<string name="english">English</string>
<string name="spanish">Spanish</string>
<string name="FetchActivityOperation_about_to_transfer_since">About to transfer data since %1$s</string>
<string name="waiting_for_reconnect">Waiting for reconnect</string>
<string name="activity_prefs_about_you">About you</string>
<string name="activity_prefs_year_birth">Year of birth</string>
<string name="activity_prefs_gender">Gender</string>
<string name="activity_prefs_height_cm">Height in cm</string>
<string name="activity_prefs_weight_kg">Weight in kg</string>
<string name="authenticating">Authenticating</string>
<string name="authentication_required">Authentication required</string>
<string name="appwidget_text">Zzz</string>
<string name="add_widget">Add widget</string>
<string name="activity_prefs_sleep_duration">Preferred sleep duration in hours</string>
<string name="appwidget_alarms_set">An alarm was set for %1$02d:%2$02d</string>
<string name="device_hw">Hardware revision: %1$s</string>
<string name="device_fw">Firmware version: %1$s</string>
<string name="error_creating_directory_for_logfiles">Error creating directory for log files: %1$s</string>
<string name="DEVINFO_HR_VER">"HR: "</string>
<string name="updatefirmwareoperation_update_in_progress">Flashing firmware</string>
<string name="updatefirmwareoperation_firmware_not_sent">Firmware not sent</string>
<string name="charts_legend_heartrate">Heart rate</string>
<string name="live_activity_heart_rate">Heart rate</string>
<string name="pref_title_pebble_health_store_raw">Store raw record in the database</string>
<string name="pref_summary_pebble_health_store_raw">If checked the data is stored \"as is\" and is available for later interpretation. NB: the database will be bigger in this case!</string>
<string name="action_db_management">Database management</string>
<string name="title_activity_db_management">Database management</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 applications and your computer. \nExpect to find your exported database (or place the database you want to import) there:</string>
<string name="activity_db_management_merge_old_title">Legacy database delete</string>
<string name="dbmanagementactivvity_cannot_access_export_path">Cannot access export path. Please contact the developers.</string>
<string name="dbmanagementactivity_exported_to">Exported to: %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">"Error exporting DB: %1$s"</string>
<string name="dbmanagementactivity_error_exporting_shared">"Error exporting preference: %1$s"</string>
<string name="dbmanagementactivity_import_data_title">Import Data?</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="dbmanagementactivity_import_successful">Imported.</string>
<string name="dbmanagementactivity_error_importing_db">"Error importing DB: %1$s"</string>
<string name="dbmanagementactivity_error_importing_shared">"Error importing preference: %1$s"</string>
<string name="dbmanagementactivity_delete_activity_data_title">Delete Activity Data?</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_database_successfully_deleted">Data deleted.</string>
<string name="dbmanagementactivity_db_deletion_failed">Database deletion failed.</string>
<string name="dbmanagementactivity_delete_old_activity_db">Delete old Activity Database?</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_old_activity_db_successfully_deleted">Old activity data deleted.</string>
<string name="dbmanagementactivity_old_activity_db_deletion_failed">Old Activity database deletion failed.</string>
<string name="dbmanagementactivity_overwrite">Overwrite</string>
<string name="Cancel">Cancel</string>
<string name="Delete">Delete</string>
<!-- Strings related to Vibration Activity -->
<string name="title_activity_vibration">Vibration</string>
<!-- Strings related to Pebble Pairing Activity-->
<string name="title_activity_pebble_pairing">Pebble pairing</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="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="pref_title_setup_bt_pairing">Enable Bluetooth pairing</string>
<string name="pref_summary_setup_bt_pairing">Deactivate this if you have trouble connecting</string>
<string name="unit_metric">Metric</string>
<string name="unit_imperial">Imperial</string>
<string name="timeformat_24h">24H</string>
<string name="timeformat_am_pm">AM/PM</string>
<string name="pref_screen_notification_profile_alarm_clock">Alarm clock</string>
<string name="activity_web_view">Web View Activity</string>
<string name="StringUtils_sender"> (%1$s)</string>
<string name="find_device_you_found_it">You found it!</string>
<string name="miband2_prefs_timeformat">Mi2: Time format</string>
<string name="mi2_fw_installhandler_fw53_hint">You need to install version %1$s before installing this firmware!</string>
<string name="mi2_enable_text_notifications">Text notifications</string>
<string name="mi2_enable_text_notifications_summary"><![CDATA[Needs firmware >= 1.0.1.28 and Mili_pro.ft* installed.]]></string>
<string name="on">On</string>
<string name="off">Off</string>
<string name="mi2_dnd_off">Off</string>
<string name="mi2_dnd_automatic">Automatic (sleep detection)</string>
<string name="mi2_dnd_scheduled">Scheduled (time interval)</string>
<string name="discovery_attempting_to_pair">Attempting to pair with %1$s</string>
<string name="discovery_bonding_failed_immediately">Bonding with %1$s failed immediately.</string>
<string name="discovery_trying_to_connect_to">Trying to connect to: %1$s</string>
<string name="discovery_enable_bluetooth">Enable Bluetooth to discover devices.</string>
<string name="discovery_successfully_bonded">Bound to %1$s.</string>
<string name="discovery_pair_title">Pair with %1$s?</string>
<string name="discovery_pair_question">Select Pair to pair your devices. If this fails, try again without pairing.</string>
<string name="discovery_yes_pair">Pair</string>
<string name="discovery_dont_pair">Don\'t Pair</string>
<!-- strings sent to pebble watches for quick actions -->
<string name="_pebble_watch_open_on_phone">Open on phone</string>
<string name="_pebble_watch_mute">Mute</string>
<string name="_pebble_watch_reply">Reply</string>
<string name="controlcenter_start_activity_tracks">Your activity tracks</string>
<string name="activity_type_not_measured">Not measured</string>
<string name="activity_type_activity">Activity</string>
<string name="activity_type_light_sleep">Light sleep</string>
<string name="activity_type_deep_sleep">Deep sleep</string>
<string name="activity_type_not_worn">Device not worn</string>
<string name="activity_type_running">Running</string>
<string name="activity_type_walking">Walking</string>
<string name="activity_type_swimming">Swimming</string>
<string name="activity_type_unknown">Unknown activity</string>
<string name="activity_summaries">Activities</string>
<string name="activity_type_biking">Biking</string>
<string name="activity_type_treadmill">Treadmill</string>
<string name="select_all">Select all</string>
<string name="share">Share</string>
<string name="reset_index">Reset fetch date</string>
<string name="kind_firmware">Firmware</string>
<string name="kind_invalid">Invalid data</string>
<string name="kind_font">Font</string>
<string name="kind_gps">GPS Firmware</string>
<string name="kind_gps_almanac">GPS Almanac</string>
<string name="kind_gps_cep">GPS Error Correction</string>
<string name="kind_resources">Resources</string>
<string name="kind_watchface">Watchface</string>
<string name="devicetype_unknown">Unknown Device</string>
<string name="devicetype_test">Test Device</string>
<string name="devicetype_pebble">Pebble</string>
<string name="devicetype_miband">Mi Band</string>
<string name="devicetype_miband2">Mi Band 2</string>
<string name="devicetype_miband3">Mi Band 3</string>
<string name="devicetype_amazfit_bip">Amazfit Bip</string>
<string name="devicetype_amazfit_cor">Amazfit Cor</string>
<string name="devicetype_vibratissimo">Vibratissimo</string>
<string name="devicetype_liveview">LiveView</string>
<string name="devicetype_hplus">HPlus</string>
<string name="devicetype_makibes_f68">Makibes F68</string>
<string name="devicetype_exrizu_k8">Exrizu K8</string>
<string name="devicetype_q8">Q8</string>
<string name="devicetype_no1_f1">No.1 F1</string>
<string name="devicetype_teclast_h30">Teclast H30</string>
<<<<<<< HEAD
<string name="devicetype_mykronoz_zetime">MyKronoz ZeTime</string>
=======
<string name="devicetype_xwatch">XWatch</string>
>>>>>>> master
<string name="choose_auto_export_location">Choose export location</string>
<string name="notification_channel_name">Gadgetbridge notifications</string>
<!-- Menus on the smart device -->
<string name="menuitem_shortcut_alipay">Alipay (Shortcut)</string>
<string name="menuitem_shortcut_weather">Weather (Shortcut)</string>
<string name="menuitem_status">Status</string>
<string name="menuitem_activity">Activity</string>
<string name="menuitem_weather">Weather</string>
<string name="menuitem_alarm">Alarm</string>
<string name="menuitem_timer">Timer</string>
<string name="menuitem_compass">Compass</string>
<string name="menuitem_settings">Settings</string>
<string name="menuitem_alipay">Alipay</string>
</resources>