From 5cd00ccbb5d508d700e13613dec870ca69a4445d Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 7 Sep 2017 23:26:24 +0200 Subject: [PATCH 01/24] Fix language switching for good Maybe :D Fixes #802 --- .../activities/AbstractGBActivity.java | 17 +++++++++++++++-- .../activities/AbstractSettingsActivity.java | 18 ++++++++++++++++-- .../activities/ControlCenterv2.java | 18 ++++++++++++++++-- .../gadgetbridge/activities/GBActivity.java | 2 +- .../activities/SettingsActivity.java | 1 + .../gadgetbridge/util/AndroidUtils.java | 8 -------- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java index 475031e23..c0d5a0092 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java @@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; public abstract class AbstractGBActivity extends AppCompatActivity implements GBActivity { + private boolean isLanguageInvalid = false; public static final int NONE = 0; public static final int NO_ACTIONBAR = 1; @@ -52,8 +53,11 @@ public abstract class AbstractGBActivity extends AppCompatActivity implements GB } }; - public void setLanguage(Locale language, boolean recreate) { - AndroidUtils.setLanguage(this, language, recreate); + public void setLanguage(Locale language, boolean invalidateLanguage) { + if (invalidateLanguage) { + isLanguageInvalid = true; + } + AndroidUtils.setLanguage(this, language); } public static void init(GBActivity activity) { @@ -88,6 +92,15 @@ public abstract class AbstractGBActivity extends AppCompatActivity implements GB super.onCreate(savedInstanceState); } + @Override + protected void onResume() { + super.onResume(); + if (isLanguageInvalid) { + isLanguageInvalid = false; + recreate(); + } + } + @Override protected void onDestroy() { LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java index a1ca99131..1cdb0a158 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java @@ -49,6 +49,8 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi private static final Logger LOG = LoggerFactory.getLogger(AbstractSettingsActivity.class); + private boolean isLanguageInvalid = false; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -152,6 +154,15 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi } } + @Override + protected void onResume() { + super.onResume(); + if (isLanguageInvalid) { + isLanguageInvalid = false; + recreate(); + } + } + @Override protected void onDestroy() { LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); @@ -210,7 +221,10 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi return super.onOptionsItemSelected(item); } - public void setLanguage(Locale language, boolean recreate) { - AndroidUtils.setLanguage(this, language, recreate); + public void setLanguage(Locale language, boolean invalidateLanguage) { + if (invalidateLanguage) { + isLanguageInvalid = true; + } + AndroidUtils.setLanguage(this, language); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java index 377663d83..171ee0159 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java @@ -78,6 +78,8 @@ public class ControlCenterv2 extends AppCompatActivity private GBDeviceAdapterv2 mGBDeviceAdapter; private RecyclerView deviceListView; + private boolean isLanguageInvalid = false; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -206,6 +208,15 @@ public class ControlCenterv2 extends AppCompatActivity } } + @Override + protected void onResume() { + super.onResume(); + if (isLanguageInvalid) { + isLanguageInvalid = false; + recreate(); + } + } + @Override protected void onDestroy() { unregisterForContextMenu(deviceListView); @@ -311,7 +322,10 @@ public class ControlCenterv2 extends AppCompatActivity ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[wantedPermissions.size()]), 0); } - public void setLanguage(Locale language, boolean recreate) { - AndroidUtils.setLanguage(this, language, recreate); + public void setLanguage(Locale language, boolean invalidateLanguage) { + if (invalidateLanguage) { + isLanguageInvalid = true; + } + AndroidUtils.setLanguage(this, language); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java index 7600c8f66..d930359ec 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java @@ -3,7 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities; import java.util.Locale; public interface GBActivity { - void setLanguage(Locale language, boolean recreate); + void setLanguage(Locale language, boolean invalidateLanguage); void setTheme(int themeId); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java index 94419a15b..16cfe61e0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java @@ -159,6 +159,7 @@ public class SettingsActivity extends AbstractSettingsActivity { String newLang = newVal.toString(); try { GBApplication.setLanguage(newLang); + recreate(); } catch (Exception ex) { GB.toast(getApplicationContext(), "Error setting language: " + ex.getLocalizedMessage(), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java index 06bafd277..067bd602b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java @@ -70,14 +70,6 @@ public class AndroidUtils { } } - public static void setLanguage(Activity activity, Locale language, boolean recreate) { - setLanguage(activity.getBaseContext(), language); - - if (recreate) { - activity.recreate(); - } - } - public static void setLanguage(Context context, Locale language) { Configuration config = new Configuration(); config.setLocale(language); From e9a68e70b585898d7b82ceef4d27e151d21d0220 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Fri, 8 Sep 2017 23:56:05 +0200 Subject: [PATCH 02/24] Make Mi2 FetchOperation reusable --- .../devices/miband/MiBand2Service.java | 2 + .../operations/AbstractFetchOperation.java | 193 ++++++++++++++++++ .../operations/FetchActivityOperation.java | 130 ++---------- 3 files changed, 208 insertions(+), 117 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java index 6fc1ce244..3c4561c4f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2Service.java @@ -207,6 +207,8 @@ public class MiBand2Service { public static final byte SUCCESS = 0x01; public static final byte COMMAND_ACTIVITY_DATA_START_DATE = 0x01; + public static final byte COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY = 0x01; + public static final byte COMMAND_ACTIVITY_DATA_TYPE_UNKNOWN_2 = 0x02; public static final byte COMMAND_ACTIVITY_DATA_XXX_DATE = 0x02; // issued on first connect, followd by COMMAND_XXXX_ACTIVITY_DATA instead of COMMAND_FETCH_ACTIVITY_DATA public static final byte COMMAND_FIRMWARE_INIT = 0x01; // to UUID_CHARACTERISTIC_FIRMWARE, followed by fw file size in bytes diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java new file mode 100644 index 000000000..548f36700 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java @@ -0,0 +1,193 @@ +/* Copyright (C) 2016-2017 Carsten Pfeiffer + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.SharedPreferences; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; +import android.widget.Toast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.text.DateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.Logging; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service; +import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.AbstractMiBand2Operation; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support; +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; +import nodomain.freeyourgadget.gadgetbridge.util.GB; + +/** + * An operation that fetches activity data. For every fetch, a new operation must + * be created, i.e. an operation may not be reused for multiple fetches. + */ +public abstract class AbstractFetchOperation extends AbstractMiBand2Operation { + private static final Logger LOG = LoggerFactory.getLogger(AbstractFetchOperation.class); + + protected byte lastPacketCounter; + protected int fetchCount; + protected BluetoothGattCharacteristic characteristicActivityData; + protected BluetoothGattCharacteristic characteristicFetch; + protected Calendar startTimestamp; + + public AbstractFetchOperation(MiBand2Support support) { + super(support); + } + + @Override + protected void enableNeededNotifications(TransactionBuilder builder, boolean enable) { + if (!enable) { + // dynamically enabled, but always disabled on finish + builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA), enable); + } + } + + @Override + protected void doPerform() throws IOException { + startFetching(); + } + + protected void startFetching() throws IOException { + lastPacketCounter = -1; + + TransactionBuilder builder = performInitialized("fetching activity data"); + getSupport().setLowLatency(builder); + if (fetchCount == 0) { + builder.add(new SetDeviceBusyAction(getDevice(), getContext().getString(R.string.busy_task_fetch_activity_data), getContext())); + } + fetchCount++; + + characteristicActivityData = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA); + builder.notify(characteristicActivityData, false); + + characteristicFetch = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4); + builder.notify(characteristicFetch, true); + + startFetching(builder); + builder.queue(getQueue()); + } + + protected abstract void startFetching(TransactionBuilder builder); + + protected abstract String getLastSyncTimeKey(); + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + UUID characteristicUUID = characteristic.getUuid(); + if (MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA.equals(characteristicUUID)) { + handleActivityNotif(characteristic.getValue()); + return true; + } else if (MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { + handleActivityMetadata(characteristic.getValue()); + return true; + } else { + return super.onCharacteristicChanged(gatt, characteristic); + } + } + + @CallSuper + protected void handleActivityFetchFinish() { + operationFinished(); + unsetBusy(); + } + + /** + * Method to handle the incoming activity data. + * There are two kind of messages we currently know: + * - the first one is 11 bytes long and contains metadata (how many bytes to expect, when the data starts, etc.) + * - the second one is 20 bytes long and contains the actual activity data + *

+ * The first message type is parsed by this method, for every other length of the value param, bufferActivityData is called. + * + * @param value + */ + protected abstract void handleActivityNotif(byte[] value); + + /** + * Creates samples from the given 17-length array + * @param value + */ + protected abstract void bufferActivityData(byte[] value); + + protected void handleActivityMetadata(byte[] value) { + if (value.length == 15) { + // first two bytes are whether our request was accepted + if (ArrayUtils.equals(value, MiBand2Service.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { + // the third byte (0x01 on success) = ? + // the 4th - 7th bytes probably somehow represent the number of bytes/packets to expect + + // last 8 bytes are the start date + Calendar startTimestamp = getSupport().fromTimeBytes(org.apache.commons.lang3.ArrayUtils.subarray(value, 7, value.length)); + setStartTimestamp(startTimestamp); + + GB.toast(getContext().getString(R.string.FetchActivityOperation_about_to_transfer_since, + DateFormat.getDateTimeInstance().format(startTimestamp.getTime())), Toast.LENGTH_LONG, GB.INFO); + } else { + LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value)); + handleActivityFetchFinish(); + } + } else if (value.length == 3) { + if (Arrays.equals(MiBand2Service.RESPONSE_FINISH_SUCCESS, value)) { + handleActivityFetchFinish(); + } else { + LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value)); + handleActivityFetchFinish(); + } + } else { + LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value)); + handleActivityFetchFinish(); + } + } + + protected void setStartTimestamp(Calendar startTimestamp) { + this.startTimestamp = startTimestamp; + } + + protected void saveLastSyncTimestamp(@NonNull GregorianCalendar timestamp) { + SharedPreferences.Editor editor = GBApplication.getPrefs().getPreferences().edit(); + editor.putLong(getLastSyncTimeKey(), timestamp.getTimeInMillis()); + editor.apply(); + } + + + protected GregorianCalendar getLastSuccessfulSyncTime() { + long timeStampMillis = GBApplication.getPrefs().getLong(getLastSyncTimeKey(), 0); + if (timeStampMillis != 0) { + GregorianCalendar calendar = BLETypeConversions.createCalendar(); + calendar.setTimeInMillis(timeStampMillis); + return calendar; + } + GregorianCalendar calendar = BLETypeConversions.createCalendar(); + calendar.add(Calendar.DAY_OF_MONTH, -10); + return calendar; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java index 927af487f..36999acec 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java @@ -16,11 +16,6 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.content.SharedPreferences; -import android.support.annotation.NonNull; -import android.support.v4.util.TimeUtils; import android.text.format.DateUtils; import android.widget.Toast; @@ -28,18 +23,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.text.DateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; -import java.util.UUID; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.Logging; -import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; @@ -51,11 +41,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support; -import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.AbstractMiBand2Operation; -import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -63,95 +50,31 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB; * An operation that fetches activity data. For every fetch, a new operation must * be created, i.e. an operation may not be reused for multiple fetches. */ -public class FetchActivityOperation extends AbstractMiBand2Operation { +public class FetchActivityOperation extends AbstractFetchOperation { private static final Logger LOG = LoggerFactory.getLogger(FetchActivityOperation.class); private List samples = new ArrayList<>(60*24); // 1day per default - private byte lastPacketCounter; - private Calendar startTimestamp; - private int fetchCount; - public FetchActivityOperation(MiBand2Support support) { super(support); } @Override - protected void enableNeededNotifications(TransactionBuilder builder, boolean enable) { - if (!enable) { - // dynamically enabled, but always disabled on finish - builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA), enable); - } + protected void startFetching() throws IOException { + samples.clear(); + super.startFetching(); } @Override - protected void doPerform() throws IOException { - startFetching(); - } - - private void startFetching() throws IOException { - samples.clear(); - lastPacketCounter = -1; - - TransactionBuilder builder = performInitialized("fetching activity data"); - getSupport().setLowLatency(builder); - if (fetchCount == 0) { - builder.add(new SetDeviceBusyAction(getDevice(), getContext().getString(R.string.busy_task_fetch_activity_data), getContext())); - } - fetchCount++; - - BluetoothGattCharacteristic characteristicActivityData = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA); - builder.notify(characteristicActivityData, false); - - BluetoothGattCharacteristic characteristicFetch = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4); - builder.notify(characteristicFetch, true); - + protected void startFetching(TransactionBuilder builder) { GregorianCalendar sinceWhen = getLastSuccessfulSyncTime(); - builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE, 0x01 }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); + builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE, MiBand2Service.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply builder.notify(characteristicActivityData, true); builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_ACTIVITY_DATA }); - builder.queue(getQueue()); } - private GregorianCalendar getLastSuccessfulSyncTime() { - long timeStampMillis = GBApplication.getPrefs().getLong(getLastSyncTimeKey(), 0); - if (timeStampMillis != 0) { - GregorianCalendar calendar = BLETypeConversions.createCalendar(); - calendar.setTimeInMillis(timeStampMillis); - return calendar; - } - GregorianCalendar calendar = BLETypeConversions.createCalendar(); - calendar.add(Calendar.DAY_OF_MONTH, -10); - return calendar; - } - - private void saveLastSyncTimestamp(@NonNull GregorianCalendar timestamp) { - SharedPreferences.Editor editor = GBApplication.getPrefs().getPreferences().edit(); - editor.putLong(getLastSyncTimeKey(), timestamp.getTimeInMillis()); - editor.apply(); - } - - private String getLastSyncTimeKey() { - return getDevice().getAddress() + "_" + "lastSyncTimeMillis"; - } - - @Override - public boolean onCharacteristicChanged(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic) { - UUID characteristicUUID = characteristic.getUuid(); - if (MiBand2Service.UUID_CHARACTERISTIC_5_ACTIVITY_DATA.equals(characteristicUUID)) { - handleActivityNotif(characteristic.getValue()); - return true; - } else if (MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { - handleActivityMetadata(characteristic.getValue()); - return true; - } else { - return super.onCharacteristicChanged(gatt, characteristic); - } - } - - private void handleActivityFetchFinish() { + protected void handleActivityFetchFinish() { LOG.info("Fetching activity data has finished round " + fetchCount); GregorianCalendar lastSyncTimestamp = saveSamples(); if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) { @@ -163,8 +86,7 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { } } - operationFinished(); - unsetBusy(); + super.handleActivityFetchFinish(); } private boolean needsAnotherFetch(GregorianCalendar lastSyncTimestamp) { @@ -232,7 +154,7 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { * * @param value */ - private void handleActivityNotif(byte[] value) { + protected void handleActivityNotif(byte[] value) { if (!isOperationRunning()) { LOG.error("ignoring activity data notification because operation is not running. Data length: " + value.length); getSupport().logMessageContent(value); @@ -257,7 +179,7 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { * Creates samples from the given 17-length array * @param value */ - private void bufferActivityData(byte[] value) { + protected void bufferActivityData(byte[] value) { int len = value.length; if (len % 4 != 1) { @@ -280,34 +202,8 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { return sample; } - private void handleActivityMetadata(byte[] value) { - if (value.length == 15) { - // first two bytes are whether our request was accepted - if (ArrayUtils.equals(value, MiBand2Service.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { - // the third byte (0x01 on success) = ? - // the 4th - 7th bytes probably somehow represent the number of bytes/packets to expect - - // last 8 bytes are the start date - Calendar startTimestamp = getSupport().fromTimeBytes(org.apache.commons.lang3.ArrayUtils.subarray(value, 7, value.length)); - setStartTimestamp(startTimestamp); - - GB.toast(getContext().getString(R.string.FetchActivityOperation_about_to_transfer_since, - DateFormat.getDateTimeInstance().format(startTimestamp.getTime())), Toast.LENGTH_LONG, GB.INFO); - } else { - LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value)); - handleActivityFetchFinish(); - } - } else if (value.length == 3) { - if (Arrays.equals(MiBand2Service.RESPONSE_FINISH_SUCCESS, value)) { - handleActivityFetchFinish(); - } else { - LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value)); - handleActivityFetchFinish(); - } - } - } - - private void setStartTimestamp(Calendar startTimestamp) { - this.startTimestamp = startTimestamp; + @Override + protected String getLastSyncTimeKey() { + return getDevice().getAddress() + "_" + "lastSyncTimeMillis"; } } From 918cc75f6ccdb19011761d4d038ed16f73a824a1 Mon Sep 17 00:00:00 2001 From: protomors Date: Fri, 8 Sep 2017 17:58:22 +0300 Subject: [PATCH 03/24] NO.1 F1: fetch sleep data. --- .../service/devices/no1f1/No1F1Support.java | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java index 8f799fed8..27f6e39d0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java @@ -114,6 +114,9 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { case No1F1Constants.CMD_FETCH_STEPS: handleStepData(data); return true; + case No1F1Constants.CMD_FETCH_SLEEP: + handleSleepData(data); + return true; case No1F1Constants.CMD_NOTIFICATION: case No1F1Constants.CMD_ICON: case No1F1Constants.CMD_DEVICE_SETTINGS: @@ -470,10 +473,18 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { } samples.clear(); LOG.info("Steps data saved"); - if (getDevice().isBusy()) { - getDevice().unsetBusyTask(); - getDevice().sendDeviceUpdateIntent(getContext()); + try { + TransactionBuilder builder = performInitialized("fetchSleep"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_FETCH_SLEEP, + (byte) 0xfa + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } + } catch (Exception ex) { GB.toast(getContext(), "Error saving step data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } @@ -498,4 +509,52 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { ); } } + + private void handleSleepData(byte[] data) { + if (data[1] == (byte) 0xfd) { + // TODO Check CRC + if (samples.size() > 0) { + try (DBHandler dbHandler = GBApplication.acquireDB()) { + Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId(); + Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId(); + No1F1SampleProvider provider = new No1F1SampleProvider(getDevice(), dbHandler.getDaoSession()); + for (int i = 0; i < samples.size(); i++) { + samples.get(i).setDeviceId(deviceId); + samples.get(i).setUserId(userId); + if (samples.get(i).getRawIntensity()<7) + samples.get(i).setRawKind(ActivityKind.TYPE_DEEP_SLEEP); + else + samples.get(i).setRawKind(ActivityKind.TYPE_LIGHT_SLEEP); + provider.addGBActivitySample(samples.get(i)); + } + samples.clear(); + LOG.info("Sleep data saved"); + if (getDevice().isBusy()) { + getDevice().unsetBusyTask(); + getDevice().sendDeviceUpdateIntent(getContext()); + } + } catch (Exception ex) { + GB.toast(getContext(), "Error saving sleep data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } + } + } else { + No1F1ActivitySample sample = new No1F1ActivitySample(); + + Calendar timestamp = GregorianCalendar.getInstance(); + timestamp.set(Calendar.YEAR, data[1] * 256 + (data[2] & 0xff)); + timestamp.set(Calendar.MONTH, (data[3] - 1) & 0xff); + timestamp.set(Calendar.DAY_OF_MONTH, data[4] & 0xff); + timestamp.set(Calendar.HOUR_OF_DAY, data[5] & 0xff); + timestamp.set(Calendar.MINUTE, data[6] & 0xff); + timestamp.set(Calendar.SECOND, 0); + + sample.setTimestamp((int) (timestamp.getTimeInMillis() / 1000L)); + sample.setRawIntensity(data[7] * 256 + (data[8] & 0xff)); + + samples.add(sample); + LOG.info("Received sleep data for " + String.format("%1$TD %1$TT", timestamp) + ": " + + sample.getRawIntensity() + " rolls" + ); + } + } } From 273c2ddbfd9c2c655d5fae76c1ce1598b72d66ea Mon Sep 17 00:00:00 2001 From: protomors Date: Sun, 10 Sep 2017 12:09:08 +0300 Subject: [PATCH 04/24] NO.1 F1: Support for heart rate measurement. --- .../gadgetbridge/daogen/GBDaoGenerator.java | 1 + .../devices/no1f1/No1F1Constants.java | 2 + .../devices/no1f1/No1F1Coordinator.java | 2 +- .../service/devices/no1f1/No1F1Support.java | 104 +++++++++++++++++- 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index b4ad0dc7f..d15e3f9af 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -265,6 +265,7 @@ public class GBDaoGenerator { 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; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java index 651fdcb48..516f5d583 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java @@ -18,6 +18,8 @@ public final class No1F1Constants { public static final byte CMD_REALTIME_STEPS = (byte) 0xb1; public static final byte CMD_FETCH_STEPS = (byte) 0xb2; public static final byte CMD_FETCH_SLEEP = (byte) 0xb3; + public static final byte CMD_REALTIME_HEARTRATE = (byte) 0xe5; + public static final byte CMD_FETCH_HEARTRATE = (byte) 0xe6; public static final byte CMD_NOTIFICATION = (byte) 0xc1; public static final byte CMD_ICON = (byte) 0xc3; public static final byte CMD_DEVICE_SETTINGS = (byte) 0xd3; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java index 4cd9dcb54..fae0b9c6a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java @@ -108,7 +108,7 @@ public class No1F1Coordinator extends AbstractDeviceCoordinator { @Override public boolean supportsHeartRateMeasurement(GBDevice device) { - return false; + return true; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java index 27f6e39d0..df079a800 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java @@ -117,6 +117,12 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { case No1F1Constants.CMD_FETCH_SLEEP: handleSleepData(data); return true; + case No1F1Constants.CMD_FETCH_HEARTRATE: + handleHeartRateData(data); + return true; + case No1F1Constants.CMD_REALTIME_HEARTRATE: + handleRealtimeHeartRateData(data); + return true; case No1F1Constants.CMD_NOTIFICATION: case No1F1Constants.CMD_ICON: case No1F1Constants.CMD_DEVICE_SETTINGS: @@ -240,7 +246,17 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { @Override public void onHeartRateTest() { - + try { + TransactionBuilder builder = performInitialized("heartRateTest"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_REALTIME_HEARTRATE, + (byte) 0x11 + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error starting heart rate measurement: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } } @Override @@ -529,10 +545,18 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { } samples.clear(); LOG.info("Sleep data saved"); - if (getDevice().isBusy()) { - getDevice().unsetBusyTask(); - getDevice().sendDeviceUpdateIntent(getContext()); + try { + TransactionBuilder builder = performInitialized("fetchHeartRate"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_FETCH_HEARTRATE, + (byte) 0xfa + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error fetching heart rate data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } + } catch (Exception ex) { GB.toast(getContext(), "Error saving sleep data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } @@ -557,4 +581,76 @@ public class No1F1Support extends AbstractBTLEDeviceSupport { ); } } + + private void handleHeartRateData(byte[] data) { + if (data[1] == (byte) 0xfd) { + // TODO Check CRC + if (samples.size() > 0) { + try (DBHandler dbHandler = GBApplication.acquireDB()) { + Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId(); + Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId(); + No1F1SampleProvider provider = new No1F1SampleProvider(getDevice(), dbHandler.getDaoSession()); + for (int i = 0; i < samples.size(); i++) { + samples.get(i).setDeviceId(deviceId); + samples.get(i).setUserId(userId); + provider.addGBActivitySample(samples.get(i)); + } + samples.clear(); + LOG.info("Heart rate data saved"); + if (getDevice().isBusy()) { + getDevice().unsetBusyTask(); + getDevice().sendDeviceUpdateIntent(getContext()); + } + } catch (Exception ex) { + GB.toast(getContext(), "Error saving heart rate data: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } + } + } else { + No1F1ActivitySample sample = new No1F1ActivitySample(); + + Calendar timestamp = GregorianCalendar.getInstance(); + timestamp.set(Calendar.YEAR, data[1] * 256 + (data[2] & 0xff)); + timestamp.set(Calendar.MONTH, (data[3] - 1) & 0xff); + timestamp.set(Calendar.DAY_OF_MONTH, data[4] & 0xff); + timestamp.set(Calendar.HOUR_OF_DAY, data[5] & 0xff); + timestamp.set(Calendar.MINUTE, data[6] & 0xff); + timestamp.set(Calendar.SECOND, 0); + + sample.setTimestamp((int) (timestamp.getTimeInMillis() / 1000L)); + sample.setHeartRate(data[7] & 0xff); + + samples.add(sample); + LOG.info("Received heart rate data for " + String.format("%1$TD %1$TT", timestamp) + ": " + + sample.getHeartRate() + " BPM" + ); + } + } + + private void handleRealtimeHeartRateData(byte[] data) { + if (data.length==2) + { + if (data[1]==(byte) 0x11) + LOG.info("Heart rate measurement started."); + else + LOG.info("Heart rate measurement stopped."); + return; + } + // Check if data is valid. Otherwise ignore sample. + if (data[2]==0) { + No1F1ActivitySample sample = new No1F1ActivitySample(); + sample.setTimestamp((int) (GregorianCalendar.getInstance().getTimeInMillis() / 1000L)); + sample.setHeartRate(data[3] & 0xff); + LOG.info("Current heart rate is: " + sample.getHeartRate() + " BPM"); + try (DBHandler dbHandler = GBApplication.acquireDB()) { + Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId(); + Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId(); + No1F1SampleProvider provider = new No1F1SampleProvider(getDevice(), dbHandler.getDaoSession()); + sample.setDeviceId(deviceId); + sample.setUserId(userId); + provider.addGBActivitySample(sample); + } catch (Exception ex) { + LOG.warn("Error saving current heart rate: " + ex.getLocalizedMessage()); + } + } + } } From b66b33239d8379546635fc2dcac0edf333eb3df3 Mon Sep 17 00:00:00 2001 From: protomors Date: Sun, 10 Sep 2017 15:07:24 +0300 Subject: [PATCH 05/24] Added database migration. --- .../gadgetbridge/daogen/GBDaoGenerator.java | 2 +- .../schema/GadgetbridgeUpdate_17.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index d15e3f9af..1f9c7bdbc 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -42,7 +42,7 @@ public class GBDaoGenerator { public static void main(String[] args) throws Exception { - Schema schema = new Schema(16, MAIN_PACKAGE + ".entities"); + Schema schema = new Schema(17, MAIN_PACKAGE + ".entities"); Entity userAttributes = addUserAttributes(schema); Entity user = addUserInfo(schema, userAttributes); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java new file mode 100644 index 000000000..c017cd92a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java @@ -0,0 +1,22 @@ +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.No1F1ActivitySampleDao; + +public class GadgetbridgeUpdate_17 implements DBUpdateScript { + @Override + public void upgradeSchema(SQLiteDatabase db) { + if (!DBHelper.existsColumn(No1F1ActivitySampleDao.TABLENAME, No1F1ActivitySampleDao.Properties.HeartRate.columnName, db)) { + String ADD_COLUMN_HEART_RATE = "ALTER TABLE " + No1F1ActivitySampleDao.TABLENAME + " ADD COLUMN " + + No1F1ActivitySampleDao.Properties.HeartRate.columnName + " INTEGER NOT NULL DEFAULT 0;"; + db.execSQL(ADD_COLUMN_HEART_RATE); + } + } + + @Override + public void downgradeSchema(SQLiteDatabase db) { + } +} From 6f702778f43fc65659606a42dfe08429f69e5b31 Mon Sep 17 00:00:00 2001 From: Gabe Schrecker Date: Sun, 10 Sep 2017 14:17:21 +0100 Subject: [PATCH 06/24] Support control of multiple media playback applications (#807) * Added Lollipop only detection of the playing media package, using MediaSessionManager. Replicates funtionality of the Official Pebble client. --- .../receivers/GBMusicControlReceiver.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java index 379475ca6..1d5bf415e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java @@ -18,17 +18,23 @@ package nodomain.freeyourgadget.gadgetbridge.service.receivers; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.media.AudioManager; +import android.media.session.MediaController; +import android.media.session.MediaSessionManager; import android.os.SystemClock; import android.view.KeyEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; +import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class GBMusicControlReceiver extends BroadcastReceiver { @@ -73,6 +79,22 @@ public class GBMusicControlReceiver extends BroadcastReceiver { Prefs prefs = GBApplication.getPrefs(); String audioPlayer = prefs.getString("audio_player", "default"); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + MediaSessionManager mediaSessionManager = + (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE); + + List controllers = mediaSessionManager.getActiveSessions( + new ComponentName(context, NotificationListener.class)); + try { + MediaController controller = controllers.get(0); + audioPlayer = controller.getPackageName(); + } catch (IndexOutOfBoundsException e) { + System.err.println("IndexOutOfBoundsException: " + e.getMessage()); + } + } + + LOG.debug("keypress: " + musicCmd.toString() + " sent to: " + audioPlayer); + long eventtime = SystemClock.uptimeMillis(); Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); From 6def9dc07e0db7c5059d766ec6df4cf6c9ce97b4 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sun, 10 Sep 2017 17:57:18 +0200 Subject: [PATCH 07/24] Pebble: allow to translate quick actions sent to the watch Fixes #789 --- .../service/devices/pebble/PebbleProtocol.java | 8 +++++--- app/src/main/res/values/strings.xml | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index 018d173c1..86e303fd6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -36,6 +36,8 @@ import java.util.Random; import java.util.SimpleTimeZone; import java.util.UUID; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement; @@ -589,9 +591,9 @@ public class PebbleProtocol extends GBDeviceProtocol { byte actions_count; short actions_length; String dismiss_string; - String open_string = "Open on phone"; - String mute_string = "Mute"; - String reply_string = "Reply"; + String open_string = GBApplication.getContext().getString(R.string._pebble_watch_open_on_phone); + String mute_string = GBApplication.getContext().getString(R.string._pebble_watch_mute); + String reply_string = GBApplication.getContext().getString(R.string._pebble_watch_reply); if (sourceName != null) { mute_string += " " + sourceName; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8038d2178..92c680cf6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -467,4 +467,9 @@ Select Pair to pair your devices. If this fails, try again without pairing. Pair Don\'t Pair + + + Open on phone + Mute + Reply From 851e47f550a22958d4ef6dd8f5045441fb0c1259 Mon Sep 17 00:00:00 2001 From: Quallenauge Date: Sun, 10 Sep 2017 20:40:10 +0200 Subject: [PATCH 08/24] Add support for EXRIZU K8 smartband. The device is compatible to HPLUS protocol. --- .../devices/hplus/EXRIZUK8Coordinator.java | 55 +++++++++++++++++++ .../gadgetbridge/model/DeviceType.java | 1 + .../service/DeviceSupportFactory.java | 3 + .../service/devices/hplus/HPlusSupport.java | 2 +- .../gadgetbridge/util/DeviceHelper.java | 2 + 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java new file mode 100644 index 000000000..668220991 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java @@ -0,0 +1,55 @@ +/* Copyright (C) 2017 Quallenauge + + 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.hplus; + +/* +* @author Quallenauge <Hamsi2k@freenet.de> +*/ + + +import android.support.annotation.NonNull; + +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +/** + * Pseudo Coordinator for the EXRIZU K8, a sub type of the HPLUS devices + */ +public class EXRIZUK8Coordinator extends HPlusCoordinator { + + @NonNull + @Override + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + String name = candidate.getDevice().getName(); + if(name != null && name.startsWith("iRun ")){ + return DeviceType.EXRIZUK8; + } + + return DeviceType.UNKNOWN; + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.EXRIZUK8; + } + + @Override + public String getManufacturer() { + return "EXRIZU"; + } + +} 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 e55c1065d..d6196f7a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -37,6 +37,7 @@ public enum DeviceType { LIVEVIEW(30, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled), HPLUS(40, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled), MAKIBESF68(41, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled), + EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled), NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled), TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled), TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled); 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 d085de772..f1439191c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -127,6 +127,9 @@ public class DeviceSupportFactory { 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 NO1F1: deviceSupport = new ServiceDeviceSupport(new No1F1Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java index 0ec1eadfb..d69ca2b91 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java @@ -160,7 +160,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport { private HPlusSupport syncPreferences(TransactionBuilder transaction) { - if (deviceType == DeviceType.HPLUS) { + if (deviceType == DeviceType.HPLUS || deviceType == DeviceType.EXRIZUK8) { setSIT(transaction); //Sync SIT Interval } 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 8420cdae4..1cc290e04 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -40,6 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipCooordinator; +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.jyou.TeclastH30Coordinator; @@ -196,6 +197,7 @@ public class DeviceHelper { result.add(new HPlusCoordinator()); result.add(new No1F1Coordinator()); result.add(new MakibesF68Coordinator()); + result.add(new EXRIZUK8Coordinator()); result.add(new TeclastH30Coordinator()); return result; From 05d0625b681f2f3ecf223e67ee09cfc5d36c646b Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Sun, 10 Sep 2017 21:11:50 +0200 Subject: [PATCH 09/24] Mi Band 2: Implement multiple button actions This enables option for multiple button actions according to the "Delay after button action". This broadcast is being sent to the intent along with button_id extra identifying how many times have the pass been done. By pass defined number of button presses is meant. --- .../devices/miband/MiBandConst.java | 1 + .../devices/miband2/MiBand2Support.java | 128 +++++++++++------- .../gadgetbridge/util/Version.java | 2 +- app/src/main/res/values-cs/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/miband_preferences.xml | 7 + 6 files changed, 94 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java index bc0078d8a..a5da45d4e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java @@ -36,6 +36,7 @@ public final class MiBandConst { public static final String PREF_MIBAND_BUTTON_ACTION_VIBRATE = "mi2_button_action_vibrate"; public static final String PREF_MIBAND_BUTTON_PRESS_COUNT = "mi_button_press_count"; public static final String PREF_MIBAND_BUTTON_PRESS_MAX_DELAY = "mi_button_press_count_max_delay"; + public static final String PREF_MIBAND_BUTTON_ACTION_DELAY = "mi_button_press_count_match_delay"; public static final String PREF_MIBAND_BUTTON_PRESS_BROADCAST = "mi_button_press_broadcast"; public static final String PREF_MIBAND_USE_HR_FOR_SLEEP_DETECTION = "mi_hr_sleep_detection"; public static final String PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS = "mi_device_time_offset_hours"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java index e8f3bd0fe..ebf0e4563 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java @@ -24,9 +24,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; import android.net.Uri; -import android.preference.PreferenceManager; import android.support.v4.content.LocalBroadcastManager; import android.text.format.DateFormat; import android.widget.Toast; @@ -42,6 +40,8 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -126,8 +126,10 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ge public class MiBand2Support extends AbstractBTLEDeviceSupport { // We introduce key press counter for notification purposes + private static int currentButtonActionId = 0; private static int currentButtonPressCount = 0; private static long currentButtonPressTime = 0; + private static long currentButtonTimerActivationTime = 0; private static final Logger LOG = LoggerFactory.getLogger(MiBand2Support.class); private final DeviceInfoProfile deviceInfoProfile; @@ -782,6 +784,80 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { // not supported } + public void runButtonAction() { + Prefs prefs = GBApplication.getPrefs(); + + if (currentButtonTimerActivationTime != currentButtonPressTime) { + return; + } + + String requiredButtonPressMessage = prefs.getString(MiBandConst.PREF_MIBAND_BUTTON_PRESS_BROADCAST, + this.getContext().getString(R.string.mi2_prefs_button_press_broadcast_default_value)); + + Intent in = new Intent(); + in.setAction(requiredButtonPressMessage); + in.putExtra("button_id", currentButtonActionId); + LOG.info("Sending " + requiredButtonPressMessage + " with button_id " + currentButtonActionId); + this.getContext().getApplicationContext().sendBroadcast(in); + if (prefs.getBoolean(MiBandConst.PREF_MIBAND_BUTTON_ACTION_VIBRATE, false)) { + performPreferredNotification(null, null, null, MiBand2Service.ALERT_LEVEL_VIBRATE_ONLY, null); + } + + currentButtonActionId = 0; + + currentButtonPressCount = 0; + currentButtonPressTime = System.currentTimeMillis(); + } + + public void handleButtonPressed(byte[] value) { + LOG.info("Button pressed"); + ///logMessageContent(value); + + // If disabled we return from function immediately + Prefs prefs = GBApplication.getPrefs(); + if (!prefs.getBoolean(MiBandConst.PREF_MIBAND_BUTTON_ACTION_ENABLE, false)) { + return; + } + + int buttonPressMaxDelay = prefs.getInt(MiBandConst.PREF_MIBAND_BUTTON_PRESS_MAX_DELAY, 2000); + int buttonActionDelay = prefs.getInt(MiBandConst.PREF_MIBAND_BUTTON_ACTION_DELAY, 0); + int requiredButtonPressCount = prefs.getInt(MiBandConst.PREF_MIBAND_BUTTON_PRESS_COUNT, 0); + + if (requiredButtonPressCount > 0) { + long timeSinceLastPress = System.currentTimeMillis() - currentButtonPressTime; + + if ((currentButtonPressTime == 0) || (timeSinceLastPress < buttonPressMaxDelay)) { + currentButtonPressCount++; + } + else { + currentButtonPressCount = 1; + currentButtonActionId = 0; + } + + currentButtonPressTime = System.currentTimeMillis(); + if (currentButtonPressCount == requiredButtonPressCount) { + currentButtonTimerActivationTime = currentButtonPressTime; + if (buttonActionDelay > 0) { + LOG.info("Activating timer"); + final Timer buttonActionTimer = new Timer("Mi Band Button Action Timer"); + buttonActionTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + runButtonAction(); + buttonActionTimer.cancel(); + } + }, buttonActionDelay, buttonActionDelay); + } + else { + LOG.info("Activating button action"); + runButtonAction(); + } + currentButtonActionId++; + currentButtonPressCount = 0; + } + } + } + @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { @@ -811,54 +887,10 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { LOG.info("Unhandled characteristic changed: " + characteristicUUID); logMessageContent(characteristic.getValue()); } + return false; } - public void handleButtonPressed(byte[] value) { - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.getContext()); - - LOG.info("Button pressed"); - logMessageContent(value); - - Prefs prefs = GBApplication.getPrefs(); - - // If disabled we return from function immediately - if (!prefs.getBoolean(MiBandConst.PREF_MIBAND_BUTTON_ACTION_ENABLE, false)) { - return; - } - - int buttonPressMaxDelay = prefs.getInt(MiBandConst.PREF_MIBAND_BUTTON_PRESS_MAX_DELAY, 2000); - int requiredButtonPressCount = prefs.getInt(MiBandConst.PREF_MIBAND_BUTTON_PRESS_COUNT, 0); - - String requiredButtonPressMessage = prefs.getString(MiBandConst.PREF_MIBAND_BUTTON_PRESS_BROADCAST, - this.getContext().getString(R.string.mi2_prefs_button_press_broadcast_default_value)); - - if (requiredButtonPressCount > 0) { - long timeSinceLastPress = System.currentTimeMillis() - currentButtonPressTime; - - if ((currentButtonPressTime == 0) || (timeSinceLastPress < buttonPressMaxDelay)) { - currentButtonPressCount++; - } - else { - currentButtonPressCount = 0; - } - - currentButtonPressTime = System.currentTimeMillis(); - if (currentButtonPressCount >= requiredButtonPressCount) { - Intent in = new Intent(); - in.setAction(requiredButtonPressMessage); - this.getContext().getApplicationContext().sendBroadcast(in); - - currentButtonPressCount = 0; - currentButtonPressTime = System.currentTimeMillis(); - - if (prefs.getBoolean(MiBandConst.PREF_MIBAND_BUTTON_ACTION_VIBRATE, false)) { - performPreferredNotification(null, null, null, MiBand2Service.ALERT_LEVEL_VIBRATE_ONLY, null); - } - } - } - } - private void handleUnknownCharacteristic(byte[] value) { } @@ -888,6 +920,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { LOG.info("Unhandled characteristic read: " + characteristicUUID); logMessageContent(characteristic.getValue()); } + return false; } @@ -1063,6 +1096,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { // getContext().getString(R.string.DEVINFO_HR_VER), // info.getSoftwareRevision())); // } + LOG.warn("Device info: " + info); versionCmd.hwVersion = info.getHardwareRevision(); // versionCmd.fwVersion = info.getFirmwareRevision(); // always null diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java index 82a397f78..62a9a7e85 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java @@ -68,4 +68,4 @@ public class Version implements Comparable { public int hashCode() { return version.hashCode(); } -} \ No newline at end of file +} diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 4d92f1c78..2d40ca1dc 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -420,6 +420,8 @@ Povolit vibrace náramku při vyslání broadcast zprávy Maximální prodleva mezi stisky Maximální prodleva mezi stisky tlačítka v milisekundách + Prodleva před akcí + Prodleva před akcí tlačítka. Umožňuje více průchodů (v extra button_id u Intent) nebo 0 pro okamžitou akci Chystáte se nainstalovat firmware %s namísto toho, který je aktuálně na vašem Amazfit Bipu. \n \nUjistěte se, že jste nainstalovali firmware .gps, pak soubor .res a nakonec soubor .fw. Hodiny se po instalaci souboru .fw restartují. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92c680cf6..14a52572d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -364,6 +364,8 @@ Enable band vibration on button action triggered Maximum delay between presses Maximum delay between button presses in milliseconds + Delay after button action + Delay after one button action match (number is in button_id intent extra) or 0 for immediately Goal notification The band will vibrate when the daily steps goal is reached Display items diff --git a/app/src/main/res/xml/miband_preferences.xml b/app/src/main/res/xml/miband_preferences.xml index 0dcc54924..a359b3b7a 100644 --- a/app/src/main/res/xml/miband_preferences.xml +++ b/app/src/main/res/xml/miband_preferences.xml @@ -72,6 +72,13 @@ android:key="mi_button_press_count_max_delay" android:summary="@string/mi2_prefs_button_press_count_max_delay_summary" android:title="@string/mi2_prefs_button_press_count_max_delay" /> + + Date: Mon, 11 Sep 2017 22:35:08 +0200 Subject: [PATCH 10/24] Bump version, add changelog --- CHANGELOG.md | 8 ++++++++ app/build.gradle | 4 ++-- app/src/main/res/xml/changelog_master.xml | 8 ++++++++ fastlane/metadata/android/en-US/changelogs/102.txt | 6 ++++++ 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/102.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bfaf57c5..5eada2143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ### Changelog +#### Version 0.21.1 +* Initial support for EXRIZU K8 (HPLus variant) +* Mi Band 2: Support multiple button actions +* NO.1 F1: Fetch sleep data +* NO.1 F1: Heart rate support +* Pebble: Support controlling the current active media playback application +* Fix suspended activities coming to front when rotating the screen + #### Version 0.21.0 * Initial NO.1 F1 support * Initial Teclast H30 support diff --git a/app/build.gradle b/app/build.gradle index a9dff3d8a..c0e7d68c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { targetSdkVersion 25 // note: always bump BOTH versionCode and versionName! - versionName "0.21.0" - versionCode 101 + versionName "0.21.1" + versionCode 102 vectorDrawables.useSupportLibrary = true } buildTypes { diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index a6d9f3501..279278358 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -1,5 +1,13 @@ + + Initial support for EXRIZU K8 (HPLus variant) + Mi Band 2: Support multiple button actions + NO.1 F1: Fetch sleep data + NO.1 F1: Heart rate support + Pebble: Support controlling the current active media playback application + Fix suspended activities coming to front when rotating the screen + Initial NO.1 F1 support Initial Teclast H30 support diff --git a/fastlane/metadata/android/en-US/changelogs/102.txt b/fastlane/metadata/android/en-US/changelogs/102.txt new file mode 100644 index 000000000..48f0aca9a --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/102.txt @@ -0,0 +1,6 @@ +* Initial support for EXRIZU K8 (HPLus variant) +* Mi Band 2: Support multiple button actions +* NO.1 F1: Fetch sleep data +* NO.1 F1: Heart rate support +* Pebble: Support controlling the current active media playback application +* Fix suspended activities coming to front when rotating the screen From b87d9d649dca97d61d54d0fe32168d9c0aefe01f Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 11 Sep 2017 23:05:49 +0200 Subject: [PATCH 11/24] Amazfit Bip: Whitelist FW 0.0.8.88 --- .../service/devices/amazfitbip/AmazfitBipFirmwareInfo.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java index c9dc6fa4d..aec1c2bee 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java @@ -45,9 +45,11 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo { static { // firmware crcToVersion.put(25257, "0.0.8.74"); + crcToVersion.put(57724, "0.0.8.88"); // resources crcToVersion.put(12586, "RES 0.0.8.74"); + crcToVersion.put(34068, "RES 0.0.8.88"); // gps crcToVersion.put(61520, "GPS 9367,8f79a91,0,0,"); From acf779a8e40e8771fbb710ee0d9461aaa0955451 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 11 Sep 2017 23:18:07 +0200 Subject: [PATCH 12/24] Amazfit Bip: fix long messages not being displayed at all --- CHANGELOG.md | 1 + .../service/devices/amazfitbip/AmazfitBipSupport.java | 2 +- app/src/main/res/xml/changelog_master.xml | 1 + fastlane/metadata/android/en-US/changelogs/102.txt | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eada2143..5725e3bcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### Version 0.21.1 * Initial support for EXRIZU K8 (HPLus variant) +* Amazfit Bip: fix long messages not being displayed at all * Mi Band 2: Support multiple button actions * NO.1 F1: Fetch sleep data * NO.1 F1: Heart rate support diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 57fb1941e..928d5c6b9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -80,7 +80,7 @@ public class AmazfitBipSupport extends MiBand2Support { try { TransactionBuilder builder = performInitialized("new notification"); AlertNotificationProfile profile = new AlertNotificationProfile(this); - profile.setMaxLength(255); // TODO: find out real limit, certainly it is more than 18 which is default + profile.setMaxLength(230); int customIconId = AmazfitBipIcon.mapToIconId(notificationSpec.type); diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index 279278358..4cf3ec831 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -2,6 +2,7 @@ Initial support for EXRIZU K8 (HPLus variant) + Amazfit Bip: fix long messages not being displayed at all Mi Band 2: Support multiple button actions NO.1 F1: Fetch sleep data NO.1 F1: Heart rate support diff --git a/fastlane/metadata/android/en-US/changelogs/102.txt b/fastlane/metadata/android/en-US/changelogs/102.txt index 48f0aca9a..942f08d96 100644 --- a/fastlane/metadata/android/en-US/changelogs/102.txt +++ b/fastlane/metadata/android/en-US/changelogs/102.txt @@ -1,4 +1,5 @@ * Initial support for EXRIZU K8 (HPLus variant) +* Amazfit Bip: fix long messages not being displayed at all * Mi Band 2: Support multiple button actions * NO.1 F1: Fetch sleep data * NO.1 F1: Heart rate support From a10fc8ad4e95a6cb0da851adc3544c4e5ce29e3f Mon Sep 17 00:00:00 2001 From: License Bot Date: Tue, 12 Sep 2017 12:39:15 +0200 Subject: [PATCH 13/24] Update license headers --- .../activities/CalBlacklistActivity.java | 2 +- .../gadgetbridge/activities/GBActivity.java | 16 ++++++++++++++++ .../database/schema/GadgetbridgeUpdate_17.java | 16 ++++++++++++++++ .../devices/hplus/EXRIZUK8Coordinator.java | 2 +- .../devices/jyou/JYouConstants.java | 16 ++++++++++++++++ .../devices/jyou/TeclastH30Coordinator.java | 17 +++++++++++++++++ .../devices/miband/MiBandConst.java | 2 +- .../devices/no1f1/No1F1Constants.java | 16 ++++++++++++++++ .../devices/no1f1/No1F1Coordinator.java | 17 +++++++++++++++++ .../devices/no1f1/No1F1SampleProvider.java | 16 ++++++++++++++++ .../gadgetbridge/model/AppNotificationType.java | 3 ++- .../gadgetbridge/model/DeviceType.java | 2 +- .../gadgetbridge/model/NotificationType.java | 4 ++-- .../service/DeviceSupportFactory.java | 3 ++- .../gadgetbridge/service/btle/GattCallback.java | 16 ---------------- .../profiles/deviceinfo/DeviceInfoProfile.java | 2 +- .../devices/amazfitbip/AmazfitBipSupport.java | 2 +- .../AmazfitBipUpdateFirmwareOperation.java | 2 +- .../service/devices/hplus/HPlusSupport.java | 2 +- .../service/devices/jyou/TeclastH30Support.java | 16 ++++++++++++++++ .../service/devices/miband2/MiBand2Support.java | 2 +- .../operations/AbstractFetchOperation.java | 2 +- .../service/devices/no1f1/No1F1Support.java | 16 ++++++++++++++++ .../receivers/GBMusicControlReceiver.java | 2 +- .../gadgetbridge/util/AndroidUtils.java | 2 +- .../gadgetbridge/util/DeviceHelper.java | 2 +- .../gadgetbridge/util/Version.java | 2 +- 27 files changed, 166 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java index 54e4ae15e..88a6b2a20 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Daniele Gobbetti +/* Copyright (C) 2017 Carsten Pfeiffer, Daniele Gobbetti This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java index d930359ec..13a5d640c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Lem Dulfo + + 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.activities; import java.util.Locale; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java index c017cd92a..04c948539 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_17.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 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; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java index 668220991..a630bb92e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/EXRIZUK8Coordinator.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Quallenauge +/* Copyright (C) 2017 João Paulo Barraca, Quallenauge This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java index 1d87f181e..8476fba57 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 Sami Alaoui + + 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.jyou; import java.util.UUID; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java index e170b64c2..993f425e6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java @@ -1,3 +1,20 @@ +/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti, protomors, Sami Alaoui + + 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.jyou; import android.annotation.TargetApi; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java index a5da45d4e..077814665 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandConst.java @@ -1,5 +1,5 @@ /* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Christian - Fischer, Daniele Gobbetti, José Rebelo, Szymon Tomasz Stefanek + Fischer, Daniele Gobbetti, José Rebelo, Michal Novotny, Szymon Tomasz Stefanek This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java index 516f5d583..05049a2b5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 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.devices.no1f1; import java.util.UUID; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java index fae0b9c6a..3ff03d642 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java @@ -1,3 +1,20 @@ +/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti, 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.devices.no1f1; import android.annotation.TargetApi; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1SampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1SampleProvider.java index e7a615fdb..2b7b1e5db 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1SampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1SampleProvider.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 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.devices.no1f1; import android.support.annotation.NonNull; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java index 349fac0c0..7e0d7b805 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java @@ -1,4 +1,5 @@ -/* Copyright (C) 2016-2017 Andreas Shimokawa, Daniele Gobbetti, Kevin Richter +/* Copyright (C) 2016-2017 Andreas Shimokawa, AnthonyDiGirolamo, Daniele + Gobbetti, Kevin Richter This file is part of Gadgetbridge. 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 d6196f7a5..eca9e1691 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -1,5 +1,5 @@ /* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Daniele - Gobbetti, João Paulo Barraca + Gobbetti, João Paulo Barraca, protomors, Quallenauge, Sami Alaoui This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java index 837dec1a9..228de8650 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java @@ -1,5 +1,5 @@ -/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Julien - Pivotto, Kevin Richter +/* Copyright (C) 2015-2017 Andreas Shimokawa, AnthonyDiGirolamo, Carsten + Pfeiffer, Julien Pivotto, Kevin Richter This file is part of Gadgetbridge. 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 f1439191c..07b1f3b1a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -1,5 +1,6 @@ /* Copyright (C) 2015-2017 0nse, Andreas Shimokawa, Carsten Pfeiffer, - Daniele Gobbetti, João Paulo Barraca, Sergey Trofimov + Daniele Gobbetti, João Paulo Barraca, protomors, Quallenauge, Sami Alaoui, + Sergey Trofimov This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattCallback.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattCallback.java index da5fe2dd5..107af38da 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattCallback.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattCallback.java @@ -1,19 +1,3 @@ -/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer - - This file is part of Gadgetbridge. - - Gadgetbridge is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Gadgetbridge is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . */ /* * Copyright (C) 2013 The Android Open Source Project * diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/deviceinfo/DeviceInfoProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/deviceinfo/DeviceInfoProfile.java index 587c8da71..92514d71a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/deviceinfo/DeviceInfoProfile.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/deviceinfo/DeviceInfoProfile.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2016-2017 Carsten Pfeiffer +/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 928d5c6b9..af877879d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Andreas Shimokawa +/* Copyright (C) 2017 Andreas Shimokawa, Carsten Pfeiffer This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/operations/AmazfitBipUpdateFirmwareOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/operations/AmazfitBipUpdateFirmwareOperation.java index 48317d550..053c81097 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/operations/AmazfitBipUpdateFirmwareOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/operations/AmazfitBipUpdateFirmwareOperation.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Andreas Shimokawa +/* Copyright (C) 2017 Andreas Shimokawa, Carsten Pfeiffer This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java index d69ca2b91..26c5f9b3d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java @@ -1,5 +1,5 @@ /* Copyright (C) 2016-2017 Alberto, Andreas Shimokawa, Carsten Pfeiffer, - ivanovlev, João Paulo Barraca, Pavel Motyrev + ivanovlev, João Paulo Barraca, Pavel Motyrev, Quallenauge This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java index 36406f6a0..d7482dd3b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 Sami Alaoui + + 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.jyou; import android.bluetooth.BluetoothGatt; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java index ebf0e4563..6c0edbe97 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java @@ -1,6 +1,6 @@ /* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Christian Fischer, Daniele Gobbetti, JohnnySun, José Rebelo, Julien Pivotto, Kasha, - Sergey Trofimov, Steffen Liebergeld + Michal Novotny, Sergey Trofimov, Steffen Liebergeld This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java index 548f36700..2c95d72f3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/AbstractFetchOperation.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2016-2017 Carsten Pfeiffer +/* Copyright (C) 2017 Carsten Pfeiffer This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java index df079a800..140db7fad 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2017 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.service.devices.no1f1; import android.bluetooth.BluetoothGatt; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java index 1d5bf415e..e008a590e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/GBMusicControlReceiver.java @@ -1,5 +1,5 @@ /* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Daniele - Gobbetti + Gobbetti, Gabe Schrecker This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java index 067bd602b..5b9f83671 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2016-2017 Carsten Pfeiffer +/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer This file is part of Gadgetbridge. 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 1cc290e04..c9342fa91 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -1,5 +1,5 @@ /* Copyright (C) 2015-2017 0nse, Andreas Shimokawa, Carsten Pfeiffer, - Daniele Gobbetti, João Paulo Barraca + Daniele Gobbetti, João Paulo Barraca, protomors, Quallenauge, Sami Alaoui This file is part of Gadgetbridge. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java index 62a9a7e85..855241cf2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/Version.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Carsten Pfeiffer +/* Copyright (C) 2017 Andreas Shimokawa, Carsten Pfeiffer, Michal Novotny This file is part of Gadgetbridge. From 78494f31557f6dc2922dc5694bc5a532800e6437 Mon Sep 17 00:00:00 2001 From: mueller-ma Date: Tue, 12 Sep 2017 19:05:44 +0200 Subject: [PATCH 14/24] Display button action settings as disabled when feature disabled Signed-off-by: mueller-ma --- app/src/main/res/xml/miband_preferences.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/res/xml/miband_preferences.xml b/app/src/main/res/xml/miband_preferences.xml index a359b3b7a..3798c8f66 100644 --- a/app/src/main/res/xml/miband_preferences.xml +++ b/app/src/main/res/xml/miband_preferences.xml @@ -49,12 +49,14 @@ Date: Fri, 8 Sep 2017 09:43:48 +0000 Subject: [PATCH 15/24] Translated using Weblate (Spanish) Currently translated at 100.0% (409 of 409 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/ --- app/src/main/res/values-es/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ae1a4b1ee..f8e6c47f4 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -411,4 +411,17 @@ \n \nEXPERIMENTAL, PROCEDE BAJO TU PROPIA RESPONSABILIDAD Firmware Amazfit Bip %1$s + Acciones del botón + Especificar acción para pulsación del botón del Mi Band 2 + Número de presiones + Número de presiones para activar el envío del mensaje + Mensaje para enviar + Enviar mensaje después de un número definido de pulsaciones + nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed + Activar acción por botón + Activar acción por un número definido de pulsaciones + Activar la vibración de la pulsera + Activar vibración por acción + Retardo máximo entre pulsaciones + Retardo máximo entre pulsaciones en milisegundos From 33aa1eff90a56339466bb03160d875284e5a828b Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 8 Sep 2017 09:56:38 +0000 Subject: [PATCH 16/24] Translated using Weblate (French) Currently translated at 100.0% (409 of 409 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/ --- app/src/main/res/values-fr/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 19e87a46e..a10091b6f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -415,4 +415,17 @@ NOTE: la base de données sera bien évidement plus grande ! \n \nEXPÉRIMENTAL, CONTINUEZ À VOS RISQUES Firmware Amazfit Bip %1$s + Actions du bouton + Spécifier les actions par pression du bouton du Mi Band 2 + Nombre de pressions du bouton + Nombre de pressions pour envoyer message + Message à envoyer + Envoyer message après nombre défini de pressions du bouton + nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed + Activer action du bouton + Activer action après nombre spécifié de pressions + Activer la vibration du bracelet + Activer la vibration après déclenchement de l\'action + Délai maximum entre pressions + Délai maximum entre pressions en millisecondes From 0e0310efa8a03ced7c15c66fd33725891b2989fb Mon Sep 17 00:00:00 2001 From: naofum Date: Sat, 9 Sep 2017 10:36:02 +0000 Subject: [PATCH 17/24] Translated using Weblate (Japanese) Currently translated at 75.0% (307 of 409 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/ --- app/src/main/res/values-ja/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 281652d35..2b1cf3d2b 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -409,4 +409,17 @@ \n \n実験的です。あなた自身の責任で行ってください Amazfit Bip ファームウェア%1$s + ボタンの動作 + Mi Band 2 ボタンを押した動作を指定します + ボタン押したカウント + ブロードキャスト メッセージをトリガーするボタンを押した数 + 送信するブロードキャスト メッセージ + ボタンを押した数で定義された数に達したブロードキャスト メッセージ + nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed + ボタンの動作を有効にする + 指定したボタンを押した数の動作を有効にします + band の振動を有効にする + ボタンの動作をトリガーに band の振動を有効にします + ボタンを押す間の最大遅延時間 + ボタンを押す間隔の最大遅延時間 (ミリ秒単位) From 3e48e97ab3d1f4fe7aa53cc0aa1a403244b39ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minori=20Hiraoka=20=28=EB=AF=B8=EB=85=B8=EB=A6=AC=29?= Date: Sat, 9 Sep 2017 12:52:01 +0000 Subject: [PATCH 18/24] Translated using Weblate (Korean) Currently translated at 35.4% (145 of 409 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ko/ --- app/src/main/res/values-ko/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 5256737b7..7e92403a0 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -7,7 +7,7 @@ 종료 동기화 수면 측정계 (초기 버전) - 잃어버린 기기 찾기... + 잃어버린 기기 찾기 스크린샷 찍기 연결 해제 디버그 @@ -46,7 +46,7 @@ SMS Pebble 메세지 일반적인 알림 지원 - … 화면이 켜져있을 때도 + …화면이 켜져있을 때도 항상 화면이 꺼져 있을 때 하지 않음 @@ -56,7 +56,7 @@ Mi Band 주소 Pebble 설정 선호하는 액티비티 트래커 - 제3자 안드로이드 앱 접근을 허용 + 제 3자 안드로이드 앱 접근을 허용 PebbleKit을 사용하는 안드로이드 앱을 실험적으로 지원 강제 알림 프로토콜 이 옵션은 펌웨어 버전에 따라 최신 알림 프로토콜을 강제로 사용하도록 합니다. 자세한 내용을 알 경우에만 이 옵션을 사용하세요. From 13b141b22fbde1bae94aeea36206c0c7cc7be164 Mon Sep 17 00:00:00 2001 From: Jonas Date: Mon, 11 Sep 2017 07:44:33 +0000 Subject: [PATCH 19/24] Translated using Weblate (French) Currently translated at 100.0% (414 of 414 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/ --- app/src/main/res/values-fr/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a10091b6f..cf284f61d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -428,4 +428,9 @@ NOTE: la base de données sera bien évidement plus grande ! Activer la vibration après déclenchement de l\'action Délai maximum entre pressions Délai maximum entre pressions en millisecondes - + Délai après action du bouton + Délai après une pression de bouton (le nombre est dans button_id intent extra) ou 0 pour immédiatement + Ouvrir sur le téléphone + Silencieux + Répondre + From 06c4a91eeefe41cf8e2b60bf37143abcc71a3d8b Mon Sep 17 00:00:00 2001 From: Jonas Date: Mon, 11 Sep 2017 07:47:15 +0000 Subject: [PATCH 20/24] Translated using Weblate (Spanish) Currently translated at 100.0% (414 of 414 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/ --- app/src/main/res/values-es/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f8e6c47f4..68fd3c432 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -424,4 +424,9 @@ Activar vibración por acción Retardo máximo entre pulsaciones Retardo máximo entre pulsaciones en milisegundos - + Retardo después de la acción del botón + Retardo después de una acción del botón (el número está en button_id intent extra) o bien 0 para efecto inmediato + Abrir en el teléfono + Silenciar + Responder + From 37b5cd626e3f080411b0b5a7daa3513ad833ef6f Mon Sep 17 00:00:00 2001 From: mueller-ma Date: Tue, 12 Sep 2017 16:55:03 +0000 Subject: [PATCH 21/24] Translated using Weblate (German) Currently translated at 99.0% (410 of 414 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/ --- app/src/main/res/values-de/strings.xml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e4eafd3b6..d1b775493 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -289,7 +289,7 @@ Aktivitätsdaten verbleiben auf dem Mi Band, auch nach der Synchronisierung. Hilfreich, wenn das Mi Band mit weiteren Apps verwendet wird. Benutze Modus mit niedriger Latenz für Firmware-Updates Dies kann bei Geräten helfen, bei denen Firmwareupdates fehlschlagen - Verlauf Schritte + Schritteverlauf Akt. Schritte pro Minute Schritte insgesamt Verlauf Schritte pro Minute @@ -385,7 +385,7 @@ Wecker (%1$s) Gefunden! - Mi2: Uhrzeit-Format + Mi2: Uhrzeitformat Installiere Version %1$s vor dem Installieren der Firmware! Text Benachrichtigung = 1.0.1.28 und installiertes Mili_pro.ft* benötigt.]]> @@ -410,4 +410,19 @@ \nHinweis: Du musst die .res and .gps Dateien nicht installieren, falls diese genau die gleichen Dateien wie die sind, die Du schon mit einer vorigen .fw Datei zusammen installiert hattest. \n \nDIES IST EXPERIMENTELL, FAHRE AUF EIGENES RISIKO FORT - + Amazfit Bip Firmware %1$s + Aktion bei Tastendruck + Bestimmte Aktion bei Tastendruck auf dem Mi Band 2 + Anzahl der Tastendrücke, die einen Broadcast auslöst + Zu Sendende Broadcast-Nachricht + Aktiviere Tastenaktion + Aktiviere Aktion bei einer bestimmten Anzahl an Tastendrücken + Aktiviere Vibration + Vibriere, wenn die Tastenaktion ausgelöst wurde + Maximale Verzögerung zwischen den Tastendrücken + Maximale Verzögerung zwischen den Tastendrücken in Millisekunden + Verzögerung nach Tastenaktion + Auf dem Smartphone öffnen + Stummschalten + Antwort + From d7152f568fc310447a913243804bbcd83e9abe48 Mon Sep 17 00:00:00 2001 From: mueller-ma Date: Tue, 12 Sep 2017 18:36:56 +0200 Subject: [PATCH 22/24] Adjust strings to meet material guidlines Signed-off-by: mueller-ma --- app/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 14a52572d..bf5fa3aa6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -92,7 +92,7 @@ Generic notification support …also when screen is on Do Not Disturb - Stop unwanted Notifications from being sent based on the Do Not Disturb mode + Stop unwanted notifications from being sent based on the Do Not Disturb mode Transliteration Enable this if your device has no support for your language\'s font @@ -158,7 +158,7 @@ Please enable network location location acquired - Force Notification Protocol + Force notification protocol This option forces using the latest notification protocol depending on the firmware version. ENABLE ONLY IF YOU KNOW WHAT YOU ARE DOING! Enable untested features Enable features that are untested. ENABLE ONLY IF YOU KNOW WHAT YOU ARE DOING! From a845f2149320728e0c1c8c7300122b3200ec4f95 Mon Sep 17 00:00:00 2001 From: mueller-ma Date: Tue, 12 Sep 2017 18:45:10 +0200 Subject: [PATCH 23/24] Make broadcast non translatable --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bf5fa3aa6..4a7279111 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -357,7 +357,7 @@ Number of button presses to trigger message broadcast Broadcast message to send Broadcast message on defined number of button presses reached - nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed + nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed Enable button action Enable action on specified number of button presses Enable band vibration From 92d79055e0a59267f77ae2b7d8a00f7300735c65 Mon Sep 17 00:00:00 2001 From: mueller-ma Date: Tue, 12 Sep 2017 18:46:18 +0200 Subject: [PATCH 24/24] Remove nontranslatable string --- app/src/main/res/values-cs/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 2d40ca1dc..793f73286 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -413,7 +413,6 @@ Definujte počet stisknutí tlačítka k vyslání broadcast zprávy Zpráva k vyslání (broadcast) Zpráva k vyslání do systému pokud počtu stisknutí tlačítka (viz výše) - nodomain.freeyourgadget.gadgetbridge.mibandButtonPressed Povolit akci tlačítka Povolit akci tlačítka na definovaný počet stisknutí Povolit vibrace náramku