diff --git a/CHANGELOG.md b/CHANGELOG.md index 784d2e82a..4656ac9f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ### Changelog +#### Version 0.21.0 (next) +* Initial NO.1 F1 support +* Amazfit Bip: Display GPS firmware version +* Amazfit Bip: Fix E-Mail notifications +* Amazfit Bip: Fix call notification with unknown caller +* Pebble: Fix crash when takeing screenshots on Android 8.0 (Oreo) +* Pebble: Support some google app icons +* Pebble: try to support spotify +* Fix language being reset to system default + #### Version 0.20.2 * Amazfit Bip: Various fixes regarding weather, add condition string support for FW 0.0.8.74 * Amazfit Bip: enable caller display in later firmwares diff --git a/README.md b/README.md index 8e713ba50..a4fbd80ac 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,13 @@ Pebble, Mi Band, Amazfit Bit and HPlus device (and more) without the vendor's cl and without the need to create an account and transmit any of your data to the vendor's servers. + [Homepage](https://gadgetbridge.org) [Blog](https://blog.gadgetbridge.org) +[![Donate](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/Gadgetbridge/donate) + [![Build](https://travis-ci.org/Freeyourgadget/Gadgetbridge.svg?branch=master)](https://travis-ci.org/Freeyourgadget/Gadgetbridge) ## Download diff --git a/app/build.gradle b/app/build.gradle index 06027cc0f..a9dff3d8a 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.20.2" - versionCode 100 + versionName "0.21.0" + versionCode 101 vectorDrawables.useSupportLibrary = true } buildTypes { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java index 10cd32ddb..5e2105583 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java @@ -59,6 +59,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.service.NotificationCollectorMonitorService; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; +import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; @@ -544,11 +545,11 @@ public class GBApplication extends Application { } else { language = new Locale(lang); } - Configuration config = new Configuration(); - config.setLocale(language); + updateLanguage(language); + } - // FIXME: I have no idea what I am doing - context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); + public static void updateLanguage(Locale locale) { + AndroidUtils.setLanguage(context, locale); Intent intent = new Intent(); intent.setAction(ACTION_LANGUAGE_CHANGE); @@ -570,6 +571,12 @@ public class GBApplication extends Application { return typedValue.data; } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateLanguage(getLanguage()); + } + public static int getBackgroundColor(Context context) { TypedValue typedValue = new TypedValue(); Resources.Theme theme = context.getTheme(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java new file mode 100644 index 000000000..475031e23 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBActivity.java @@ -0,0 +1,96 @@ +/* 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 android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v7.app.AppCompatActivity; + +import java.util.Locale; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; + + +public abstract class AbstractGBActivity extends AppCompatActivity implements GBActivity { + + public static final int NONE = 0; + public static final int NO_ACTIONBAR = 1; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + switch (action) { + case GBApplication.ACTION_LANGUAGE_CHANGE: + setLanguage(GBApplication.getLanguage(), true); + break; + case GBApplication.ACTION_QUIT: + finish(); + break; + } + } + }; + + public void setLanguage(Locale language, boolean recreate) { + AndroidUtils.setLanguage(this, language, recreate); + } + + public static void init(GBActivity activity) { + init(activity, NONE); + } + + public static void init(GBActivity activity, int flags) { + if (GBApplication.isDarkThemeEnabled()) { + if ((flags & NO_ACTIONBAR) != 0) { + activity.setTheme(R.style.GadgetbridgeThemeDark_NoActionBar); + } else { + activity.setTheme(R.style.GadgetbridgeThemeDark); + } + } else { + if ((flags & NO_ACTIONBAR) != 0) { + activity.setTheme(R.style.GadgetbridgeTheme_NoActionBar); + } else { + activity.setTheme(R.style.GadgetbridgeTheme); + } + } + activity.setLanguage(GBApplication.getLanguage(), false); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + IntentFilter filterLocal = new IntentFilter(); + filterLocal.addAction(GBApplication.ACTION_QUIT); + filterLocal.addAction(GBApplication.ACTION_LANGUAGE_CHANGE); + LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal); + + init(this); + super.onCreate(savedInstanceState); + } + + @Override + protected void onDestroy() { + LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); + super.onDestroy(); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBFragmentActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBFragmentActivity.java index 087954de7..2390aedff 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBFragmentActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractGBFragmentActivity.java @@ -33,7 +33,7 @@ import android.support.v4.app.FragmentPagerAdapter; * * @see AbstractGBFragment */ -public abstract class AbstractGBFragmentActivity extends GBActivity { +public abstract class AbstractGBFragmentActivity extends AbstractGBActivity { /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a 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 14d37112a..a1ca99131 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java @@ -37,7 +37,6 @@ import org.slf4j.LoggerFactory; import java.util.Locale; import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; /** @@ -46,7 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; * to set that listener in #onCreate, *not* in #onPostCreate, otherwise the value will * not be displayed. */ -public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivity { +public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivity implements GBActivity { private static final Logger LOG = LoggerFactory.getLogger(AbstractSettingsActivity.class); @@ -56,7 +55,7 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi String action = intent.getAction(); switch (action) { case GBApplication.ACTION_LANGUAGE_CHANGE: - setLanguage(GBApplication.getLanguage()); + setLanguage(GBApplication.getLanguage(), true); break; case GBApplication.ACTION_QUIT: finish(); @@ -129,11 +128,7 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi @Override protected void onCreate(Bundle savedInstanceState) { - if (GBApplication.isDarkThemeEnabled()) { - setTheme(R.style.GadgetbridgeThemeDark); - } else { - setTheme(R.style.GadgetbridgeTheme); - } + AbstractGBActivity.init(this); IntentFilter filterLocal = new IntentFilter(); filterLocal.addAction(GBApplication.ACTION_QUIT); @@ -215,7 +210,7 @@ public abstract class AbstractSettingsActivity extends AppCompatPreferenceActivi return super.onOptionsItemSelected(item); } - private void setLanguage(Locale language) { - AndroidUtils.setLanguage(this, language); + public void setLanguage(Locale language, boolean recreate) { + AndroidUtils.setLanguage(this, language, recreate); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java index 543673de3..d0cfa085d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -31,7 +31,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; -public class AlarmDetails extends GBActivity { +public class AlarmDetails extends AbstractGBActivity { private GBAlarm alarm; private TimePicker timePicker; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AndroidPairingActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AndroidPairingActivity.java index f26dd3b04..a2c39bbcf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AndroidPairingActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AndroidPairingActivity.java @@ -20,7 +20,7 @@ import android.os.Bundle; import nodomain.freeyourgadget.gadgetbridge.R; -public class AndroidPairingActivity extends GBActivity { +public class AndroidPairingActivity extends AbstractGBActivity { @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AppBlacklistActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AppBlacklistActivity.java index 5c3c10146..20ea96cc9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AppBlacklistActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AppBlacklistActivity.java @@ -31,7 +31,7 @@ import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.adapter.AppBlacklistAdapter; -public class AppBlacklistActivity extends GBActivity { +public class AppBlacklistActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(AppBlacklistActivity.class); private AppBlacklistAdapter appBlacklistAdapter; 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 15307a32c..54e4ae15e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/CalBlacklistActivity.java @@ -47,7 +47,7 @@ import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.util.GB; -public class CalBlacklistActivity extends GBActivity { +public class CalBlacklistActivity extends AbstractGBActivity { private final String[] EVENT_PROJECTION = new String[]{ CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java index 584ac07da..3528c82be 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -38,7 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS; -public class ConfigureAlarms extends GBActivity { +public class ConfigureAlarms extends AbstractGBActivity { private static final int REQ_CONFIGURE_ALARM = 1; 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 7e889efa1..377663d83 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java @@ -62,9 +62,9 @@ import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; -//TODO: extend GBActivity, but it requires actionbar that is not available +//TODO: extend AbstractGBActivity, but it requires actionbar that is not available public class ControlCenterv2 extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener { + implements NavigationView.OnNavigationItemSelectedListener, GBActivity { //needed for KK compatibility static { @@ -84,7 +84,7 @@ public class ControlCenterv2 extends AppCompatActivity String action = intent.getAction(); switch (action) { case GBApplication.ACTION_LANGUAGE_CHANGE: - setLanguage(GBApplication.getLanguage()); + setLanguage(GBApplication.getLanguage(), true); break; case GBApplication.ACTION_QUIT: finish(); @@ -98,11 +98,7 @@ public class ControlCenterv2 extends AppCompatActivity @Override protected void onCreate(Bundle savedInstanceState) { - if (GBApplication.isDarkThemeEnabled()) { - setTheme(R.style.GadgetbridgeThemeDark_NoActionBar); - } else { - setTheme(R.style.GadgetbridgeTheme_NoActionBar); - } + AbstractGBActivity.init(this, AbstractGBActivity.NO_ACTIONBAR); super.onCreate(savedInstanceState); setContentView(R.layout.activity_controlcenterv2); @@ -315,7 +311,7 @@ public class ControlCenterv2 extends AppCompatActivity ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[wantedPermissions.size()]), 0); } - private void setLanguage(Locale language) { - AndroidUtils.setLanguage(this, language); + public void setLanguage(Locale language, boolean recreate) { + AndroidUtils.setLanguage(this, language, recreate); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DbManagementActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DbManagementActivity.java index 2085f7615..782f43a24 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DbManagementActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DbManagementActivity.java @@ -45,7 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.ImportExportSharedPreferences; -public class DbManagementActivity extends GBActivity { +public class DbManagementActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(DbManagementActivity.class); private static SharedPreferences sharedPrefs; private ImportExportSharedPreferences shared_file = new ImportExportSharedPreferences(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index a88df172e..03e3cecdf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -53,7 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.util.GB; -public class DebugActivity extends GBActivity { +public class DebugActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(DebugActivity.class); private static final String EXTRA_REPLY = "reply"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java index 6c80cf76a..b7af301cf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java @@ -69,7 +69,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB; import static android.bluetooth.le.ScanSettings.MATCH_MODE_STICKY; import static android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY; -public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemClickListener { +public class DiscoveryActivity extends AbstractGBActivity implements AdapterView.OnItemClickListener { private static final Logger LOG = LoggerFactory.getLogger(DiscoveryActivity.class); private static final long SCAN_DURATION = 60000; // 60s diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java index cc70d4f7c..ca4790eb0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java @@ -40,7 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.WebViewSingleton; -public class ExternalPebbleJSActivity extends GBActivity { +public class ExternalPebbleJSActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(ExternalPebbleJSActivity.class); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java index f1f5ac229..28b57e464 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java @@ -51,7 +51,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; -public class FwAppInstallerActivity extends GBActivity implements InstallActivity { +public class FwAppInstallerActivity extends AbstractGBActivity implements InstallActivity { private static final Logger LOG = LoggerFactory.getLogger(FwAppInstallerActivity.class); private static final String ITEM_DETAILS = "details"; 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 09246d6dc..7600c8f66 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/GBActivity.java @@ -1,80 +1,9 @@ -/* 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 android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.LocaleList; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.AppCompatActivity; - import java.util.Locale; -import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.R; -import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager; -import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; -import nodomain.freeyourgadget.gadgetbridge.util.Prefs; +public interface GBActivity { + void setLanguage(Locale language, boolean recreate); + void setTheme(int themeId); - -public class GBActivity extends AppCompatActivity { - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - switch (action) { - case GBApplication.ACTION_LANGUAGE_CHANGE: - setLanguage(GBApplication.getLanguage()); - break; - case GBApplication.ACTION_QUIT: - finish(); - break; - } - } - }; - - private void setLanguage(Locale language) { - AndroidUtils.setLanguage(this, language); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - IntentFilter filterLocal = new IntentFilter(); - filterLocal.addAction(GBApplication.ACTION_QUIT); - filterLocal.addAction(GBApplication.ACTION_LANGUAGE_CHANGE); - LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal); - - if (GBApplication.isDarkThemeEnabled()) { - setTheme(R.style.GadgetbridgeThemeDark); - } else { - setTheme(R.style.GadgetbridgeTheme); - } - super.onCreate(savedInstanceState); - } - - @Override - protected void onDestroy() { - LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); - super.onDestroy(); - } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/VibrationActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/VibrationActivity.java index ea92116a6..076d8d1c3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/VibrationActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/VibrationActivity.java @@ -26,7 +26,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; -public class VibrationActivity extends GBActivity { +public class VibrationActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(VibrationActivity.class); private SeekBar seekBar; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPairingActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPairingActivity.java index deed2c2e0..4e49ae911 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPairingActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandPairingActivity.java @@ -37,7 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2; import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity; -import nodomain.freeyourgadget.gadgetbridge.activities.GBActivity; +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; @@ -46,7 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; -public class MiBandPairingActivity extends GBActivity { +public class MiBandPairingActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(MiBandPairingActivity.class); private static final int REQ_CODE_USER_SETTINGS = 52; 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 new file mode 100644 index 000000000..e839955e0 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Constants.java @@ -0,0 +1,31 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.no1f1; + +import java.util.UUID; + +public final class No1F1Constants { + + public static final UUID UUID_CHARACTERISTIC_CONTROL = UUID.fromString("000033f1-0000-1000-8000-00805f9b34fb"); + public static final UUID UUID_CHARACTERISTIC_MEASURE = UUID.fromString("000033f2-0000-1000-8000-00805f9b34fb"); + public static final UUID UUID_SERVICE_NO1 = UUID.fromString("000055ff-0000-1000-8000-00805f9b34fb"); + + public static final byte CMD_DISPLAY_SETTINGS = (byte) 0xa0; + public static final byte CMD_FIRMWARE_VERSION = (byte) 0xa1; + public static final byte CMD_BATTERY = (byte) 0xa2; + public static final byte CMD_DATETIME = (byte) 0xa3; + public static final byte CMD_USER_DATA = (byte) 0xa9; + public static final byte CMD_ALARM = (byte) 0xab; + public static final byte CMD_FACTORY_RESET = (byte) 0xad; + 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; + public static final byte CMD_HEARTRATE_SETTINGS = (byte) 0xd6; + + public static final byte NOTIFICATION_HEADER = (byte) 0x01; + public static final byte NOTIFICATION_CALL = (byte) 0x02; + public static final byte NOTIFICATION_SMS = (byte) 0x03; + public static final byte NOTIFICATION_STOP = (byte) 0x04; // to stop showing incoming call + + public static final byte ICON_QQ = (byte) 0x01; + public static final byte ICON_WECHAT = (byte) 0x02; + public static final byte ICON_ALARM = (byte) 0x04; +} 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 new file mode 100644 index 000000000..bb51683a6 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java @@ -0,0 +1,140 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.no1f1; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.bluetooth.le.ScanFilter; +import android.content.Context; +import android.net.Uri; +import android.os.Build; +import android.os.ParcelUuid; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Collection; +import java.util.Collections; + +import nodomain.freeyourgadget.gadgetbridge.GBException; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +public class No1F1Coordinator extends AbstractDeviceCoordinator { + + @NonNull + @Override + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public Collection createBLEScanFilters() { + ParcelUuid hpService = new ParcelUuid(No1F1Constants.UUID_SERVICE_NO1); + ScanFilter filter = new ScanFilter.Builder().setServiceUuid(hpService).build(); + return Collections.singletonList(filter); + } + + @NonNull + @Override + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + String name = candidate.getDevice().getName(); + if (name != null && name.startsWith("X-RUN")) { + return DeviceType.NO1F1; + } + + return DeviceType.UNKNOWN; + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.NO1F1; + } + + @Override + public int getBondingStyle(GBDevice deviceCandidate) { + return BONDING_STYLE_NONE; + } + + @Nullable + @Override + public Class getPairingActivity() { + return null; + } + + @Nullable + @Override + public Class getPrimaryActivity() { + return null; + } + + @Override + public boolean supportsActivityDataFetching() { + return false; + } + + @Override + public boolean supportsActivityTracking() { + return false; + } + + @Override + public SampleProvider getSampleProvider(GBDevice device, DaoSession session) { + return null; + } + + @Override + public InstallHandler findInstallHandler(Uri uri, Context context) { + return null; + } + + @Override + public boolean supportsScreenshots() { + return false; + } + + @Override + public boolean supportsAlarmConfiguration() { + return false; + } + + @Override + public boolean supportsSmartWakeup(GBDevice device) { + return false; + } + + @Override + public boolean supportsHeartRateMeasurement(GBDevice device) { + return false; + } + + @Override + public String getManufacturer() { + return "NO1"; + } + + @Override + public boolean supportsAppsManagement() { + return false; + } + + @Override + public Class getAppsManagementActivity() { + return null; + } + + @Override + public boolean supportsCalendarEvents() { + return false; + } + + @Override + public boolean supportsRealtimeData() { + return false; + } + + @Override + protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { + + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebblePairingActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebblePairingActivity.java index f7823a01e..30d0b6d39 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebblePairingActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebblePairingActivity.java @@ -38,7 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2; import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity; -import nodomain.freeyourgadget.gadgetbridge.activities.GBActivity; +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; @@ -50,7 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; -public class PebblePairingActivity extends GBActivity { +public class PebblePairingActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(PebblePairingActivity.class); private TextView message; private boolean isPairing; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationConfig.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationConfig.java index d7caa1e8a..93e4dcb2c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationConfig.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationConfig.java @@ -19,9 +19,9 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents; import android.os.Bundle; import nodomain.freeyourgadget.gadgetbridge.R; -import nodomain.freeyourgadget.gadgetbridge.activities.GBActivity; +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity; -public class WeatherNotificationConfig extends GBActivity { +public class WeatherNotificationConfig extends AbstractGBActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java index f1c095b11..2444aabcc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java @@ -61,6 +61,7 @@ public class GBDevice implements Parcelable { private static final String DEVINFO_HW_VER = "HW: "; private static final String DEVINFO_FW_VER = "FW: "; private static final String DEVINFO_HR_VER = "HR: "; + private static final String DEVINFO_GPS_VER = "GPS: "; private static final String DEVINFO_ADDR = "ADDR: "; private static final String DEVINFO_ADDR2 = "ADDR2: "; private String mName; @@ -165,7 +166,7 @@ public class GBDevice implements Parcelable { } /** - * Sets the second firmware version, typically the heart rate firmware version + * Sets the second firmware version (HR or GPS or other component) * @param firmwareVersion2 */ public void setFirmwareVersion2(String firmwareVersion2) { @@ -445,7 +446,12 @@ public class GBDevice implements Parcelable { result.add(new GenericItem(DEVINFO_FW_VER, mFirmwareVersion)); } if (mFirmwareVersion2 != null) { - result.add(new GenericItem(DEVINFO_HR_VER, mFirmwareVersion2)); + // FIXME: thats ugly + if (mDeviceType == DeviceType.AMAZFITBIP) { + result.add(new GenericItem(DEVINFO_GPS_VER, mFirmwareVersion2)); + } else { + result.add(new GenericItem(DEVINFO_HR_VER, mFirmwareVersion2)); + } } if (mAddress != null) { result.add(new GenericItem(DEVINFO_ADDR, mAddress)); 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 209666250..d543f913d 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), + NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled), TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled); private final int key; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index a8ae4616a..24e014b9e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -229,7 +229,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("image/*"); - shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(fullpath))); + shareIntent.putExtra(Intent.EXTRA_STREAM, screenshotURI); PendingIntent pendingShareIntent = PendingIntent.getActivity(context, 0, Intent.createChooser(shareIntent, "share screenshot"), PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index cf4d77664..73e89821e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -189,7 +189,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere "net.sourceforge.subsonic.androidapp.EVENT_META_CHANGED", "com.maxmpz.audioplayer.TPOS_SYNC", "com.maxmpz.audioplayer.STATUS_CHANGED", - "com.maxmpz.audioplayer.PLAYING_MODE_CHANGED"}; + "com.maxmpz.audioplayer.PLAYING_MODE_CHANGED", + "com.spotify.music.metadatachanged", + "com.spotify.music.playbackstatechanged" + }; /** * For testing! 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 86a8f0a74..f17a5eec8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -32,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSup import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.no1f1.No1F1Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.vibratissimo.VibratissimoSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport; @@ -125,6 +126,9 @@ public class DeviceSupportFactory { case MAKIBESF68: deviceSupport = new ServiceDeviceSupport(new HPlusSupport(DeviceType.MAKIBESF68), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; + case NO1F1: + deviceSupport = new ServiceDeviceSupport(new No1F1Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); + break; } if (deviceSupport != null) { deviceSupport.setContext(gbDevice, mBtAdapter, mContext); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java index 1c64f025c..3b9e847ab 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java @@ -85,6 +85,9 @@ public abstract class AbstractBTLEOperation * You MUST call this method when the operation has finished, either * successfully or unsuccessfully. * + * Subclasses must ensure that the {@link BtLEQueue queue's}'s gatt callback (set on the transaction builder by {@link #performInitialized(String)}) + * is being unset, otherwise it will continue to receive events until another transaction is being executed by the queue. + * * @throws IOException */ protected void operationFinished() throws IOException { 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 c0e46acea..587c8da71 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 @@ -110,49 +110,49 @@ public class DeviceInfoProfile extends Abst private void handleManufacturerName(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String name = characteristic.getStringValue(0); + String name = characteristic.getStringValue(0).trim(); deviceInfo.setManufacturerName(name); notify(createIntent(deviceInfo)); } private void handleModelNumber(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String modelNumber = characteristic.getStringValue(0); + String modelNumber = characteristic.getStringValue(0).trim(); deviceInfo.setModelNumber(modelNumber); notify(createIntent(deviceInfo)); } private void handleSerialNumber(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String serialNumber = characteristic.getStringValue(0); + String serialNumber = characteristic.getStringValue(0).trim(); deviceInfo.setSerialNumber(serialNumber); notify(createIntent(deviceInfo)); } private void handleHardwareRevision(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String hardwareRevision = characteristic.getStringValue(0); + String hardwareRevision = characteristic.getStringValue(0).trim(); deviceInfo.setHardwareRevision(hardwareRevision); notify(createIntent(deviceInfo)); } private void handleFirmwareRevision(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String firmwareRevision = characteristic.getStringValue(0); + String firmwareRevision = characteristic.getStringValue(0).trim(); deviceInfo.setFirmwareRevision(firmwareRevision); notify(createIntent(deviceInfo)); } private void handleSoftwareRevision(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String softwareRevision = characteristic.getStringValue(0); + String softwareRevision = characteristic.getStringValue(0).trim(); deviceInfo.setSoftwareRevision(softwareRevision); notify(createIntent(deviceInfo)); } private void handleSystemId(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - String systemId = characteristic.getStringValue(0); + String systemId = characteristic.getStringValue(0).trim(); deviceInfo.setSystemId(systemId); notify(createIntent(deviceInfo)); } private void handleRegulatoryCertificationData(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // TODO: regulatory certification data list not supported yet -// String regulatoryCertificationData = characteristic.getStringValue(0); +// String regulatoryCertificationData = characteristic.getStringValue(0).trim(); // deviceInfo.setRegulatoryCertificationDataList(regulatoryCertificationData); // notify(createIntent(deviceInfo)); } 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 fe23fa7c2..23b2f37bb 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 @@ -89,6 +89,10 @@ public class AmazfitBipSupport extends MiBand2Support { if (notificationSpec.type == NotificationType.GENERIC_SMS) { alertCategory = AlertCategory.SMS; } + // EMAIL icon does not work in FW 0.0.8.74, it did in 0.0.7.90 + else if (notificationSpec.type == NotificationType.GENERIC_EMAIL) { + alertCategory = AlertCategory.Email; + } NewAlert alert = new NewAlert(alertCategory, 1, message, customIconId); profile.newAlert(builder, alert); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java index d7c9fac61..866f2f30b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java @@ -40,7 +40,7 @@ class AmazfitBipTextNotificationStrategy extends Mi2TextNotificationStrategy { @Override protected void sendCustomNotification(VibrationProfile vibrationProfile, SimpleNotification simpleNotification, BtLEAction extraAction, TransactionBuilder builder) { - if (simpleNotification != null && !StringUtils.isEmpty(simpleNotification.getMessage())) { + if (simpleNotification != null) { sendAlert(simpleNotification, builder); } } 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 a27c7ef08..48317d550 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 @@ -16,34 +16,24 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations; +import android.content.Context; import android.net.Uri; -import android.widget.Toast; import java.io.IOException; import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipFWHelper; import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.UpdateFirmwareOperation; -import nodomain.freeyourgadget.gadgetbridge.util.GB; public class AmazfitBipUpdateFirmwareOperation extends UpdateFirmwareOperation { public AmazfitBipUpdateFirmwareOperation(Uri uri, AmazfitBipSupport support) { super(uri, support); } - @Override - protected void doPerform() throws IOException { - AmazfitBipFWHelper mFwHelper = new AmazfitBipFWHelper(uri, getContext()); - firmwareInfo = mFwHelper.getFirmwareInfo(); - if (!firmwareInfo.isGenerallyCompatibleWith(getDevice())) { - throw new IOException("Firmware is not compatible with the given device: " + getDevice().getAddress()); - } - - if (!sendFwInfo()) { - displayMessage(getContext(), "Error sending firmware info, aborting.", Toast.LENGTH_LONG, GB.ERROR); - done(); - } - //the firmware will be sent by the notification listener if the band confirms that the metadata are ok. + protected Mi2FirmwareInfo createFwInfo(Uri uri, Context context) throws IOException { + AmazfitBipFWHelper fwHelper = new AmazfitBipFWHelper(uri, getContext()); + return fwHelper.getFirmwareInfo(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/AbstractMiBandOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/AbstractMiBandOperation.java index 2c1180e34..4dacf9fb0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/AbstractMiBandOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/operations/AbstractMiBandOperation.java @@ -48,6 +48,7 @@ public abstract class AbstractMiBandOperation alarms) { + + } + + @Override + public void onSetCallState(CallSpec callSpec) { + if (callSpec.command == CallSpec.CALL_INCOMING) { + showNotification(No1F1Constants.NOTIFICATION_CALL, callSpec.name, callSpec.number); + setVibration(3, 5); + } else { + stopNotification(); + setVibration(0, 0); + } + } + + @Override + public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) { + + } + + @Override + public void onSetMusicState(MusicStateSpec stateSpec) { + + } + + @Override + public void onSetMusicInfo(MusicSpec musicSpec) { + + } + + @Override + public void onEnableRealtimeSteps(boolean enable) { + + } + + @Override + public void onInstallApp(Uri uri) { + + } + + @Override + public void onAppInfoReq() { + + } + + @Override + public void onAppStart(UUID uuid, boolean start) { + + } + + @Override + public void onAppDelete(UUID uuid) { + + } + + @Override + public void onAppConfiguration(UUID appUuid, String config) { + + } + + @Override + public void onAppReorder(UUID[] uuids) { + + } + + @Override + public void onFetchActivityData() { + + } + + @Override + public void onReboot() { + try { + TransactionBuilder builder = performInitialized("clearNotification"); + byte[] msg = new byte[]{ + (byte) 0xad + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + } + } + + @Override + public void onHeartRateTest() { + + } + + @Override + public void onEnableRealtimeHeartRateMeasurement(boolean enable) { + + } + + @Override + public void onFindDevice(boolean start) { + if (start) + setVibration(3, 10); + else + setVibration(0, 0); + } + + @Override + public void onSetConstantVibration(int integer) { + + } + + @Override + public void onScreenshotReq() { + + } + + @Override + public void onEnableHeartRateSleepSupport(boolean enable) { + + } + + @Override + public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) { + + } + + @Override + public void onDeleteCalendarEvent(byte type, long id) { + + } + + @Override + public void onSendConfiguration(String config) { + + } + + @Override + public void onTestNewFunction() { + + } + + @Override + public void onSendWeather(WeatherSpec weatherSpec) { + + } + + @Override + public boolean useAutoConnect() { + return true; + } + + private void sendSettings(TransactionBuilder builder) { + // TODO Create custom settings page for changing hardcoded values + + // set date and time + Calendar c = GregorianCalendar.getInstance(); + byte[] datetimeBytes = new byte[]{ + No1F1Constants.CMD_DATETIME, + (byte) ((c.get(Calendar.YEAR) / 256) & 0xff), + (byte) (c.get(Calendar.YEAR) % 256), + (byte) (c.get(Calendar.MONTH) + 1), + (byte) c.get(Calendar.DAY_OF_MONTH), + (byte) c.get(Calendar.HOUR_OF_DAY), + (byte) c.get(Calendar.MINUTE), + (byte) c.get(Calendar.SECOND) + }; + builder.write(ctrlCharacteristic, datetimeBytes); + + // set user data + ActivityUser activityUser = new ActivityUser(); + byte[] userBytes = new byte[]{ + No1F1Constants.CMD_USER_DATA, + 0, + (byte) Math.round(activityUser.getHeightCm() * 0.43), // step length in cm + 0, + (byte) activityUser.getWeightKg(), + 5, // screen on time + 0, + 0, + (byte) (activityUser.getStepsGoal() / 256), + (byte) (activityUser.getStepsGoal() % 256), + 1, // unknown + (byte) 0xff, // unknown + 0, + (byte) activityUser.getAge(), + 0 + }; + if (activityUser.getGender() == ActivityUser.GENDER_FEMALE) + userBytes[14] = 2; // female + else + userBytes[14] = 1; // male + + builder.write(ctrlCharacteristic, userBytes); + + // more settings + builder.write(ctrlCharacteristic, new byte[]{ + No1F1Constants.CMD_DEVICE_SETTINGS, + 0x00, // 1 - turns on inactivity alarm + 0x3c, + 0x02, + 0x03, + 0x01, + 0x00 + }); + + // display settings + builder.write(ctrlCharacteristic, new byte[]{ + No1F1Constants.CMD_DISPLAY_SETTINGS, + 0x01, // 1 - display distance in kilometers, 2 - in miles + 0x01 // 1 - display 24-hour clock, 2 - for 12-hour with AM/PM + }); + + // heart rate measurement mode + builder.write(ctrlCharacteristic, new byte[]{ + No1F1Constants.CMD_HEARTRATE_SETTINGS, + 0x02, // 1 - static (measure for 15 seconds), 2 - realtime + }); + + // periodic heart rate measurement + builder.write(ctrlCharacteristic, new byte[]{ + No1F1Constants.CMD_HEARTRATE_SETTINGS, + 0x01, + 0x02 // measure heart rate every 2 hours (0 to turn off) + }); + } + + private void setVibration(int duration, int count) { + try { + TransactionBuilder builder = performInitialized("vibrate"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_ALARM, + 0, + 0, + 0, + (byte) duration, + (byte) count, + 2, + 1 + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + } + } + + private void showIcon(int iconId) { + try { + TransactionBuilder builder = performInitialized("showIcon"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_ICON, + (byte) iconId + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + } + } + + private void showNotification(int type, String header, String body) { + try { + // TODO Add transliteration. + TransactionBuilder builder = performInitialized("showNotification"); + int length; + byte[] bytes; + byte[] msg; + + // send header + bytes = header.toString().getBytes("EUC-JP"); + length = min(bytes.length, 18); + msg = new byte[length + 2]; + msg[0] = No1F1Constants.CMD_NOTIFICATION; + msg[1] = No1F1Constants.NOTIFICATION_HEADER; + System.arraycopy(bytes, 0, msg, 2, length); + builder.write(ctrlCharacteristic, msg); + + // send body + bytes = header.toString().getBytes("EUC-JP"); + length = min(bytes.length, 18); + msg = new byte[length + 2]; + msg[0] = No1F1Constants.CMD_NOTIFICATION; + msg[1] = (byte) type; + System.arraycopy(bytes, 0, msg, 2, length); + builder.write(ctrlCharacteristic, msg); + + performConnected(builder.getTransaction()); + } catch (IOException e) { + } + } + + private void stopNotification() { + try { + TransactionBuilder builder = performInitialized("clearNotification"); + byte[] msg = new byte[]{ + No1F1Constants.CMD_NOTIFICATION, + No1F1Constants.NOTIFICATION_STOP + }; + builder.write(ctrlCharacteristic, msg); + performConnected(builder.getTransaction()); + } catch (IOException e) { + } + } +} 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 a3258b19f..06bafd277 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java @@ -70,13 +70,20 @@ public class AndroidUtils { } } - public static void setLanguage(Activity activity, Locale language) { + 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); // FIXME: I have no idea what I am doing - activity.getBaseContext().getResources().updateConfiguration(config, activity.getBaseContext().getResources().getDisplayMetrics()); - activity.recreate(); + context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); } /** 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 d2c81d20e..e3241d6a6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -46,6 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator; import nodomain.freeyourgadget.gadgetbridge.entities.Device; @@ -192,6 +193,7 @@ public class DeviceHelper { result.add(new VibratissimoCoordinator()); result.add(new LiveviewCoordinator()); result.add(new HPlusCoordinator()); + result.add(new No1F1Coordinator()); result.add(new MakibesF68Coordinator()); return result; diff --git a/app/src/main/res/drawable/level_list_device.xml b/app/src/main/res/drawable/level_list_device.xml index 9347fd997..eb68abe6e 100644 --- a/app/src/main/res/drawable/level_list_device.xml +++ b/app/src/main/res/drawable/level_list_device.xml @@ -9,6 +9,7 @@ + @@ -19,5 +20,6 @@ + \ No newline at end of file