Merge branch 'master' into db-refactoring

master
cpfeiffer 2016-04-29 22:28:53 +02:00
commit 64a6b9a936
61 changed files with 642 additions and 228 deletions

View File

@ -1,4 +1,20 @@
###Changelog
####Version (0.9.6)
* Again some UI/theme improvements
* New preference to reconnect after connection loss (defaults to true)
* Fix crash when dealing with certain old preference values
* Mi Band: automatically reconnect when back in range after connection loss
* Mi Band 1S: display heart rate value again when invoked via the Debug view
####Version (0.9.5)
* Several UI Improvements
* Easier First-time setup by using a FAB
* Optional Dark Theme
* Notification App Blacklist is now sorted
* Gadgetbridge Icon in the notification bar displays connection state
* Logging is now configurable without restart
* Mi Band 1S: Initial live heartrate tracking
* Fix certain crash in charts activity on slower devices (#277)
####Version (0.9.4)
* Pebble: support pebble health datalog messages of firmware 3.11 (this adds support for deep sleep!)

View File

@ -16,8 +16,8 @@ android {
targetSdkVersion 23
// note: always bump BOTH versionCode and versionName!
versionName "0.9.4"
versionCode 48
versionName "0.9.6"
versionCode 50
}
buildTypes {
release {

View File

@ -7,11 +7,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.content.res.Resources;
import android.os.Build;
import android.os.Build.VERSION;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.util.TypedValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -23,6 +25,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBConstants;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
@ -33,7 +37,9 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
//import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
@ -54,6 +60,9 @@ public class GBApplication extends Application {
private static final int CURRENT_PREFS_VERSION = 2;
private static LimitedQueue mIDSenderLookup = new LimitedQueue(16);
private static DaoSession daoSession;
private static Appender<ILoggingEvent> fileLogger;
private static Prefs prefs;
private static GBPrefs gbPrefs;
public static final String ACTION_QUIT
= "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit";
@ -87,10 +96,12 @@ public class GBApplication extends Application {
super.onCreate();
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs = new Prefs(sharedPrefs);
gbPrefs = new GBPrefs(prefs);
// don't do anything here before we set up logging, otherwise
// slf4j may be implicitly initialized before we properly configured it.
setupLogging();
setupLogging(isFileLoggingEnabled());
if (getPrefsFileVersion() != CURRENT_PREFS_VERSION) {
migratePrefs(getPrefsFileVersion());
@ -125,35 +136,71 @@ public class GBApplication extends Application {
}
public static boolean isFileLoggingEnabled() {
return sharedPrefs.getBoolean("log_to_file", false);
return prefs.getBoolean("log_to_file", false);
}
private void setupLogging() {
if (isFileLoggingEnabled()) {
try {
public static void setupLogging(boolean enable) {
try {
if (fileLogger == null) {
File dir = FileUtils.getExternalFilesDir();
// used by assets/logback.xml since the location cannot be statically determined
System.setProperty("GB_LOGFILES_DIR", dir.getAbsolutePath());
getLogger().info("Gadgetbridge version: " + BuildConfig.VERSION_NAME);
} catch (IOException ex) {
Log.e("GBApplication", "External files dir not available, cannot log to file", ex);
removeFileLogger();
rememberFileLogger();
}
} else {
removeFileLogger();
if (enable) {
startFileLogger();
} else {
stopFileLogger();
}
getLogger().info("Gadgetbridge version: " + BuildConfig.VERSION_NAME);
} catch (IOException ex) {
Log.e("GBApplication", "External files dir not available, cannot log to file", ex);
stopFileLogger();
}
}
private void removeFileLogger() {
private static void startFileLogger() {
if (fileLogger != null && !fileLogger.isStarted()) {
addFileLogger(fileLogger);
fileLogger.start();
}
}
private static void stopFileLogger() {
if (fileLogger != null && fileLogger.isStarted()) {
fileLogger.stop();
removeFileLogger(fileLogger);
}
}
private static void rememberFileLogger() {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
fileLogger = root.getAppender("FILE");
}
private static void addFileLogger(Appender<ILoggingEvent> fileLogger) {
try {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.detachAppender("FILE");
if (!root.isAttached(fileLogger)) {
root.addAppender(fileLogger);
}
} catch (Throwable ex) {
Log.e("GBApplication", "Error removing logger FILE appender", ex);
}
}
private Logger getLogger() {
private static void removeFileLogger(Appender<ILoggingEvent> fileLogger) {
try {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
if (root.isAttached(fileLogger)) {
root.detachAppender(fileLogger);
}
} catch (Throwable ex) {
Log.e("GBApplication", "Error removing logger FILE appender", ex);
}
}
private static Logger getLogger() {
return LoggerFactory.getLogger(GBApplication.class);
}
@ -320,6 +367,27 @@ public class GBApplication extends Application {
}
public static boolean isDarkThemeEnabled() {
return sharedPrefs.getString("pref_key_theme", context.getString(R.string.pref_theme_value_light)).equals(context.getString(R.string.pref_theme_value_dark));
return prefs.getString("pref_key_theme", context.getString(R.string.pref_theme_value_light)).equals(context.getString(R.string.pref_theme_value_dark));
}
public static int getTextColor(Context context) {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
theme.resolveAttribute(android.R.attr.textColor, typedValue, true);
return typedValue.data;
}
public static int getBackgroundColor(Context context) {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
theme.resolveAttribute(android.R.attr.background, typedValue, true);
return typedValue.data;
}
public static Prefs getPrefs() {
return prefs;
}
public static GBPrefs getGBPrefs() {
return gbPrefs;
}
}

View File

@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@ -12,6 +13,7 @@ import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
@ -41,6 +43,14 @@ public abstract class AbstractSettingsActivity extends PreferenceActivity {
private static class SimpleSetSummaryOnChangeListener implements Preference.OnPreferenceChangeListener {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
if (preference instanceof EditTextPreference) {
if (((EditTextPreference) preference).getEditText().getKeyListener().getInputType() == InputType.TYPE_CLASS_NUMBER) {
if ("".equals(String.valueOf(value))) {
// reject empty numeric input
return false;
}
}
}
updateSummary(preference, value);
return true;
}

View File

@ -4,11 +4,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
@ -47,7 +45,6 @@ public class AppBlacklistActivity extends GBActivity {
}
};
private SharedPreferences sharedPrefs;
private IdentityHashMap<ApplicationInfo, String> nameMap;
@Override
@ -56,7 +53,6 @@ public class AppBlacklistActivity extends GBActivity {
setContentView(R.layout.activity_appblacklist);
final PackageManager pm = getPackageManager();
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
final List<ApplicationInfo> packageList = pm.getInstalledApplications(PackageManager.GET_META_DATA);
ListView appListView = (ListView) findViewById(R.id.appListView);

View File

@ -4,10 +4,8 @@ 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.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v4.content.LocalBroadcastManager;
import android.view.ContextMenu;
@ -34,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class AppManagerActivity extends GBActivity {
@ -59,7 +58,7 @@ public class AppManagerActivity extends GBActivity {
appList.add(new GBDeviceApp(uuid, appName, appCreator, "", appType));
}
if (sharedPrefs.getBoolean("pebble_force_untested", false)) {
if (prefs.getBoolean("pebble_force_untested", false)) {
appList.addAll(getSystemApps());
}
@ -68,7 +67,7 @@ public class AppManagerActivity extends GBActivity {
}
};
private SharedPreferences sharedPrefs;
private Prefs prefs;
private final List<GBDeviceApp> appList = new ArrayList<>();
private GBDeviceAppAdapter mGBDeviceAppAdapter;
@ -130,7 +129,7 @@ public class AppManagerActivity extends GBActivity {
throw new IllegalArgumentException("Must provide a device when invoking this activity");
}
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs = GBApplication.getPrefs();
setContentView(R.layout.activity_appmanager);
@ -150,7 +149,7 @@ public class AppManagerActivity extends GBActivity {
appList.addAll(getCachedApps());
if (sharedPrefs.getBoolean("pebble_force_untested", false)) {
if (prefs.getBoolean("pebble_force_untested", false)) {
appList.addAll(getSystemApps());
}

View File

@ -1,9 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.MenuItem;
import android.widget.ListView;
@ -16,6 +14,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS;
@ -34,12 +33,12 @@ public class ConfigureAlarms extends GBActivity {
setContentView(R.layout.activity_configure_alarms);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
Prefs prefs = GBApplication.getPrefs();
preferencesAlarmListSet = prefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
if (preferencesAlarmListSet.isEmpty()) {
//initialize the preferences
preferencesAlarmListSet = new HashSet<>(Arrays.asList(GBAlarm.DEFAULT_ALARMS));
sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, preferencesAlarmListSet).apply();
prefs.getPreferences().edit().putStringSet(PREF_MIBAND_ALARMS, preferencesAlarmListSet).apply();
}
mGBAlarmListAdapter = new GBAlarmListAdapter(this, preferencesAlarmListSet);
@ -66,9 +65,9 @@ public class ConfigureAlarms extends GBActivity {
}
private void updateAlarmsFromPrefs() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
int reservedSlots = Integer.parseInt(sharedPrefs.getString(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, "0"));
Prefs prefs = GBApplication.getPrefs();
preferencesAlarmListSet = prefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
mGBAlarmListAdapter.setAlarmList(preferencesAlarmListSet, reservedSlots);
mGBAlarmListAdapter.notifyDataSetChanged();

View File

@ -10,11 +10,9 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
@ -46,6 +44,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class ControlCenter extends GBActivity {
@ -184,9 +183,9 @@ public class ControlCenter extends GBActivity {
/*
* Ask for permission to intercept notifications on first run.
*/
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPrefs.getBoolean("firstrun", true)) {
sharedPrefs.edit().putBoolean("firstrun", false).apply();
Prefs prefs = GBApplication.getPrefs();
if (prefs.getBoolean("firstrun", true)) {
prefs.getPreferences().edit().putBoolean("firstrun", false).apply();
Intent enableIntent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(enableIntent);
}

View File

@ -13,6 +13,7 @@ import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.RemoteInput;
import android.support.v4.content.LocalBroadcastManager;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
@ -29,6 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
@ -63,15 +65,22 @@ public class DebugActivity extends GBActivity {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case GBApplication.ACTION_QUIT:
case GBApplication.ACTION_QUIT: {
finish();
break;
case ACTION_REPLY:
}
case ACTION_REPLY: {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
CharSequence reply = remoteInput.getCharSequence(EXTRA_REPLY);
LOG.info("got wearable reply: " + reply);
GB.toast(context, "got wearable reply: " + reply, Toast.LENGTH_SHORT, GB.INFO);
break;
}
case DeviceService.ACTION_HEARTRATE_MEASUREMENT: {
int hrValue = intent.getIntExtra(DeviceService.EXTRA_HEART_RATE_VALUE, -1);
GB.toast(DebugActivity.this, "Heart Rate measured: " + hrValue, Toast.LENGTH_LONG, GB.INFO);
break;
}
}
}
};
@ -84,7 +93,9 @@ public class DebugActivity extends GBActivity {
IntentFilter filter = new IntentFilter();
filter.addAction(GBApplication.ACTION_QUIT);
filter.addAction(ACTION_REPLY);
registerReceiver(mReceiver, filter);
filter.addAction(DeviceService.ACTION_HEARTRATE_MEASUREMENT);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
registerReceiver(mReceiver, filter); // for ACTION_REPLY
editContent = (EditText) findViewById(R.id.editContent);
sendSMSButton = (Button) findViewById(R.id.sendSMSButton);
@ -348,6 +359,7 @@ public class DebugActivity extends GBActivity {
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
unregisterReceiver(mReceiver);
}

View File

@ -12,6 +12,7 @@ import android.widget.Toast;
import java.io.IOException;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@ -88,16 +89,18 @@ public class SettingsActivity extends AbstractSettingsActivity {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
if (Boolean.TRUE.equals(newVal)) {
try {
boolean doEnable = Boolean.TRUE.equals(newVal);
try {
if (doEnable) {
FileUtils.getExternalFilesDir(); // ensures that it is created
} catch (IOException ex) {
GB.toast(getApplicationContext(),
getString(R.string.error_creating_directory_for_logfiles, ex.getLocalizedMessage()),
Toast.LENGTH_LONG,
GB.ERROR,
ex);
}
GBApplication.setupLogging(doEnable);
} catch (IOException ex) {
GB.toast(getApplicationContext(),
getString(R.string.error_creating_directory_for_logfiles, ex.getLocalizedMessage()),
Toast.LENGTH_LONG,
GB.ERROR,
ex);
}
return true;
}

View File

@ -4,13 +4,11 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager;
import android.util.TypedValue;
import android.view.View;
import com.github.mikephil.charting.charts.BarLineChartBase;
@ -39,6 +37,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
@ -151,13 +150,8 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
}
protected void init() {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = getContext().getTheme();
theme.resolveAttribute(android.R.attr.background, typedValue, true);
BACKGROUND_COLOR = typedValue.data;
theme.resolveAttribute(android.R.attr.textColor, typedValue, true);
LEGEND_TEXT_COLOR = DESCRIPTION_COLOR = typedValue.data;
BACKGROUND_COLOR = GBApplication.getBackgroundColor(getContext());
LEGEND_TEXT_COLOR = DESCRIPTION_COLOR = GBApplication.getTextColor(getContext());
CHART_TEXT_COLOR = getResources().getColor(R.color.secondarytext);
HEARTRATE_COLOR = getResources().getColor(R.color.chart_heartrate);
HEARTRATE_FILL_COLOR = getResources().getColor(R.color.chart_heartrate_fill);

View File

@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
@ -152,7 +153,7 @@ public class GBAlarmListAdapter extends ArrayAdapter<GBAlarm> {
if (isOn) {
view.setTextColor(Color.BLUE);
} else {
view.setTextColor(Color.BLACK);
view.setTextColor(GBApplication.getTextColor(mContext));
}
}
}

View File

@ -6,16 +6,16 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class PebbleContentProvider extends ContentProvider {
@ -59,8 +59,8 @@ public class PebbleContentProvider extends ContentProvider {
MatrixCursor mc = new MatrixCursor(columnNames);
int connected = 0;
int appMessage = 0;
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.getContext());
if (sharedPrefs.getBoolean("pebble_enable_pebblekit", false)) {
Prefs prefs = GBApplication.getPrefs();
if (prefs.getBoolean("pebble_enable_pebblekit", false)) {
appMessage = 1;
}
if (mGBDevice != null && mGBDevice.getType() == DeviceType.PEBBLE && mGBDevice.isInitialized()) {

View File

@ -1,10 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.devices.miband;
import android.content.SharedPreferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public final class MiBandConst {
private static final Logger LOG = LoggerFactory.getLogger(MiBandConst.class);
@ -27,19 +27,12 @@ public final class MiBandConst {
public static final String MI_1A = "1A";
public static final String MI_1S = "1S";
public static int getNotificationPrefIntValue(String pref, String origin, SharedPreferences prefs, int defaultValue) {
public static int getNotificationPrefIntValue(String pref, String origin, Prefs prefs, int defaultValue) {
String key = getNotificationPrefKey(pref, origin);
String value = null;
try {
value = prefs.getString(key, String.valueOf(defaultValue));
return Integer.valueOf(value);
} catch (NumberFormatException ex) {
LOG.error("Error converting preference value to int: " + key + ": " + value);
return defaultValue;
}
return prefs.getInt(key, defaultValue);
}
public static String getNotificationPrefStringValue(String pref, String origin, SharedPreferences prefs, String defaultValue) {
public static String getNotificationPrefStringValue(String pref, String origin, Prefs prefs, String defaultValue) {
String key = getNotificationPrefKey(pref, origin);
return prefs.getString(key, defaultValue);
}

View File

@ -2,9 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices.miband;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,6 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class MiBandCoordinator extends AbstractDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MiBandCoordinator.class);
@ -112,7 +111,7 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
*/
public static UserInfo getConfiguredUserInfo(String miBandAddress) throws IllegalArgumentException {
ActivityUser activityUser = new ActivityUser();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Prefs prefs = GBApplication.getPrefs();
UserInfo info = UserInfo.create(
miBandAddress,
@ -128,7 +127,7 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
public static int getWearLocation(String miBandAddress) throws IllegalArgumentException {
int location = 0; //left hand
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Prefs prefs = GBApplication.getPrefs();
if ("right".equals(prefs.getString(MiBandConst.PREF_MIBAND_WEARSIDE, "left"))) {
location = 1; // right hand
}
@ -136,17 +135,17 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
}
public static boolean getHeartrateSleepSupport(String miBandAddress) throws IllegalArgumentException {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Prefs prefs = GBApplication.getPrefs();
return prefs.getBoolean(MiBandConst.PREF_MIBAND_USE_HR_FOR_SLEEP_DETECTION, false);
}
public static int getFitnessGoal(String miBandAddress) throws IllegalArgumentException {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
return Integer.parseInt(prefs.getString(MiBandConst.PREF_MIBAND_FITNESS_GOAL, "10000"));
Prefs prefs = GBApplication.getPrefs();
return prefs.getInt(MiBandConst.PREF_MIBAND_FITNESS_GOAL, 10000);
}
public static int getReservedAlarmSlots(String miBandAddress) throws IllegalArgumentException {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
return Integer.parseInt(prefs.getString(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, "0"));
Prefs prefs = GBApplication.getPrefs();
return prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
}
}

View File

@ -7,11 +7,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.TextView;
import android.widget.Toast;
@ -26,6 +24,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class MiBandPairingActivity extends Activity {
private static final Logger LOG = LoggerFactory.getLogger(MiBandPairingActivity.class);
@ -170,8 +169,8 @@ public class MiBandPairingActivity extends Activity {
unregisterReceiver(mBondingReceiver);
if (pairedSuccessfully) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
sharedPrefs.edit().putString(MiBandConst.PREF_MIBAND_ADDRESS, macAddress).apply();
Prefs prefs = GBApplication.getPrefs();
prefs.getPreferences().edit().putString(MiBandConst.PREF_MIBAND_ADDRESS, macAddress).apply();
}
Intent intent = new Intent(this, ControlCenter.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

View File

@ -2,9 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices.pebble;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.AppManagerActivity;
@ -14,6 +12,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class PebbleCoordinator extends AbstractDeviceCoordinator {
public PebbleCoordinator() {
@ -45,8 +44,8 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator {
@Override
public SampleProvider getSampleProvider() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
int activityTracker = Integer.parseInt(sharedPrefs.getString("pebble_activitytracker", Integer.toString(SampleProvider.PROVIDER_PEBBLE_HEALTH)));
Prefs prefs = GBApplication.getPrefs();
int activityTracker = prefs.getInt("pebble_activitytracker", SampleProvider.PROVIDER_PEBBLE_HEALTH);
switch (activityTracker) {
case SampleProvider.PROVIDER_PEBBLE_HEALTH:
return new HealthSampleProvider();

View File

@ -4,12 +4,11 @@ import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class BluetoothStateChangeReceiver extends BroadcastReceiver {
@Override
@ -22,8 +21,8 @@ public class BluetoothStateChangeReceiver extends BroadcastReceiver {
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if (!sharedPrefs.getBoolean("general_autoconnectonbluetooth", false)) {
Prefs prefs = GBApplication.getPrefs();
if (!prefs.getBoolean("general_autoconnectonbluetooth", false)) {
return;
}

View File

@ -3,11 +3,9 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -15,6 +13,7 @@ import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class K9Receiver extends BroadcastReceiver {
@ -24,11 +23,11 @@ public class K9Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if ("never".equals(sharedPrefs.getString("notification_mode_k9mail", "when_screen_off"))) {
Prefs prefs = GBApplication.getPrefs();
if ("never".equals(prefs.getString("notification_mode_k9mail", "when_screen_off"))) {
return;
}
if ("when_screen_off".equals(sharedPrefs.getString("notification_mode_k9mail", "when_screen_off"))) {
if ("when_screen_off".equals(prefs.getString("notification_mode_k9mail", "when_screen_off"))) {
PowerManager powermanager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powermanager.isScreenOn()) {
return;

View File

@ -8,12 +8,10 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.support.v4.app.NotificationCompat;
@ -30,6 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class NotificationListener extends NotificationListenerService {
@ -161,8 +160,8 @@ public class NotificationListener extends NotificationListenerService {
return;
}
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!sharedPrefs.getBoolean("notifications_generic_whenscreenon", false)) {
Prefs prefs = GBApplication.getPrefs();
if (!prefs.getBoolean("notifications_generic_whenscreenon", false)) {
PowerManager powermanager = (PowerManager) getSystemService(POWER_SERVICE);
if (powermanager.isScreenOn()) {
return;
@ -189,13 +188,13 @@ public class NotificationListener extends NotificationListenerService {
}
if (source.equals("eu.siacs.conversations")) {
if (!"never".equals(sharedPrefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
if (!"never".equals(prefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
return;
}
}
if (source.equals("com.fsck.k9")) {
if (!"never".equals(sharedPrefs.getString("notification_mode_k9mail", "when_screen_off"))) {
if (!"never".equals(prefs.getString("notification_mode_k9mail", "when_screen_off"))) {
return;
}
}
@ -205,7 +204,7 @@ public class NotificationListener extends NotificationListenerService {
source.equals("com.sonyericsson.conversations") ||
source.equals("com.android.messaging") ||
source.equals("org.smssecure.smssecure")) {
if (!"never".equals(sharedPrefs.getString("notification_mode_sms", "when_screen_off"))) {
if (!"never".equals(prefs.getString("notification_mode_sms", "when_screen_off"))) {
return;
}
}

View File

@ -3,9 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import org.json.JSONArray;
import org.json.JSONException;
@ -15,6 +13,7 @@ import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class PebbleReceiver extends BroadcastReceiver {
@ -23,11 +22,11 @@ public class PebbleReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if ("never".equals(sharedPrefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
Prefs prefs = GBApplication.getPrefs();
if ("never".equals(prefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
return;
}
if ("when_screen_off".equals(sharedPrefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
if ("when_screen_off".equals(prefs.getString("notification_mode_pebblemsg", "when_screen_off"))) {
PowerManager powermanager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powermanager.isScreenOn()) {
return;

View File

@ -3,12 +3,11 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class PhoneCallReceiver extends BroadcastReceiver {
@ -64,8 +63,8 @@ public class PhoneCallReceiver extends BroadcastReceiver {
break;
}
if (callCommand != CallSpec.CALL_UNDEFINED) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if ("never".equals(sharedPrefs.getString("notification_mode_calls", "always"))) {
Prefs prefs = GBApplication.getPrefs();
if ("never".equals(prefs.getString("notification_mode_calls", "always"))) {
return;
}
CallSpec callSpec = new CallSpec();

View File

@ -3,26 +3,24 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if ("never".equals(sharedPrefs.getString("notification_mode_sms", "when_screen_off"))) {
Prefs prefs = GBApplication.getPrefs();
if ("never".equals(prefs.getString("notification_mode_sms", "when_screen_off"))) {
return;
}
if ("when_screen_off".equals(sharedPrefs.getString("notification_mode_sms", "when_screen_off"))) {
if ("when_screen_off".equals(prefs.getString("notification_mode_sms", "when_screen_off"))) {
PowerManager powermanager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powermanager.isScreenOn()) {
return;

View File

@ -3,8 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,6 +12,7 @@ import java.util.GregorianCalendar;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class TimeChangeReceiver extends BroadcastReceiver {
@ -22,10 +21,10 @@ public class TimeChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Prefs prefs = GBApplication.getPrefs();
final String action = intent.getAction();
if (sharedPrefs.getBoolean("datetime_synconconnect", true) && (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED))) {
if (prefs.getBoolean("datetime_synconconnect", true) && (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED))) {
Date newTime = GregorianCalendar.getInstance().getTime();
LOG.info("Time or Timezone changed, syncing with device: " + DateTimeUtils.formatDate(newTime) + " (" + newTime.toGMTString() + "), " + intent.getAction());
GBApplication.deviceService().onSetTime();

View File

@ -1,8 +1,6 @@
package nodomain.freeyourgadget.gadgetbridge.impl;
import android.content.SharedPreferences;
import android.os.Parcel;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import java.util.Calendar;
@ -12,6 +10,7 @@ import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS;
@ -187,8 +186,8 @@ public class GBAlarm implements Alarm {
}
public void store() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Set<String> preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
Prefs prefs = GBApplication.getPrefs();
Set<String> preferencesAlarmListSet = prefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet<String>());
//the old Set cannot be updated in place see http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet%28java.lang.String,%20java.util.Set%3Cjava.lang.String%3E%29
Set<String> newPrefs = new HashSet<>(preferencesAlarmListSet);
@ -202,7 +201,7 @@ public class GBAlarm implements Alarm {
}
}
newPrefs.add(this.toPreferences());
sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, newPrefs).apply();
prefs.getPreferences().edit().putStringSet(PREF_MIBAND_ALARMS, newPrefs).apply();
}
public static final Creator CREATOR = new Creator() {

View File

@ -1,11 +1,9 @@
package nodomain.freeyourgadget.gadgetbridge.model;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import java.util.Calendar;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
* Class holding the common user information needed by most activity trackers
@ -86,11 +84,11 @@ public class ActivityUser {
}
private void fetchPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
activityUserGender = Integer.parseInt(prefs.getString(PREF_USER_GENDER, Integer.toString(defaultUserGender)));
activityUserHeightCm = Integer.parseInt(prefs.getString(PREF_USER_HEIGHT_CM, Integer.toString(defaultUserHeightCm)));
activityUserWeightKg = Integer.parseInt(prefs.getString(PREF_USER_WEIGHT_KG, Integer.toString(defaultUserWeightKg)));
activityUserYearOfBirth = Integer.parseInt(prefs.getString(PREF_USER_YEAR_OF_BIRTH, Integer.toString(defaultUserYearOfBirth)));
activityUserSleepDuration = Integer.parseInt(prefs.getString(PREF_USER_SLEEP_DURATION, Integer.toString(defaultUserSleepDuration)));
Prefs prefs = GBApplication.getPrefs();
activityUserGender = prefs.getInt(PREF_USER_GENDER, defaultUserGender);
activityUserHeightCm = prefs.getInt(PREF_USER_HEIGHT_CM, defaultUserHeightCm);
activityUserWeightKg = prefs.getInt(PREF_USER_WEIGHT_KG, defaultUserWeightKg);
activityUserYearOfBirth = prefs.getInt(PREF_USER_YEAR_OF_BIRTH, defaultUserYearOfBirth);
activityUserSleepDuration = prefs.getInt(PREF_USER_SLEEP_DURATION, defaultUserSleepDuration);
}
}

View File

@ -6,11 +6,9 @@ import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.SmsManager;
@ -44,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
// TODO: support option for a single reminder notification when notifications could not be delivered?
// conditions: app was running and received notifications, but device was not connected.
@ -60,6 +59,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
protected GBDevice gbDevice;
private BluetoothAdapter btAdapter;
private Context context;
private boolean autoReconnect;
public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) {
this.gbDevice = gbDevice;
@ -82,6 +82,16 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
return gbDevice.isInitialized();
}
@Override
public void setAutoReconnect(boolean enable) {
autoReconnect = enable;
}
@Override
public boolean getAutoReconnect() {
return autoReconnect;
}
@Override
public GBDevice getDevice() {
return gbDevice;
@ -247,8 +257,8 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
Intent notificationListenerIntent = new Intent(action);
notificationListenerIntent.putExtra("handle", deviceEvent.handle);
if (deviceEvent.reply != null) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
String suffix = sharedPrefs.getString("canned_reply_suffix", null);
Prefs prefs = GBApplication.getPrefs();
String suffix = prefs.getString("canned_reply_suffix", null);
if (suffix != null && !Objects.equals(suffix, "")) {
deviceEvent.reply += suffix;
}

View File

@ -10,7 +10,6 @@ import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
@ -39,6 +38,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CALLSTATE;
@ -89,7 +90,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOT
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_PERFORM_PAIR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
public class DeviceCommunicationService extends Service {
public class DeviceCommunicationService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
private boolean mStarted = false;
@ -131,6 +132,10 @@ public class DeviceCommunicationService extends Service {
super.onCreate();
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED));
mFactory = new DeviceSupportFactory(this);
if (hasPrefs()) {
getPrefs().getPreferences().registerOnSharedPreferenceChangeListener(this);
}
}
@Override
@ -170,7 +175,7 @@ public class DeviceCommunicationService extends Service {
// when we get past this, we should have valid mDeviceSupport and mGBDevice instances
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Prefs prefs = getPrefs();
switch (action) {
case ACTION_START:
start();
@ -181,8 +186,8 @@ public class DeviceCommunicationService extends Service {
String btDeviceAddress = null;
if (gbDevice == null) {
btDeviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
if (btDeviceAddress == null && sharedPrefs != null) { // may be null in test cases
btDeviceAddress = sharedPrefs.getString("last_device_address", null);
if (btDeviceAddress == null && prefs != null) { // may be null in test cases
btDeviceAddress = prefs.getString("last_device_address", null);
}
if (btDeviceAddress != null) {
gbDevice = DeviceHelper.getInstance().findAvailableDevice(btDeviceAddress, this);
@ -191,8 +196,10 @@ public class DeviceCommunicationService extends Service {
btDeviceAddress = gbDevice.getAddress();
}
if (sharedPrefs != null) {
sharedPrefs.edit().putString("last_device_address", btDeviceAddress).apply();
boolean autoReconnect = GBPrefs.AUTO_RECONNECT_DEFAULT;
if (prefs != null && prefs.getPreferences() != null) {
prefs.getPreferences().edit().putString("last_device_address", btDeviceAddress).apply();
autoReconnect = getGBPrefs().getAutoReconnect();
}
if (gbDevice != null && !isConnecting() && !isConnected()) {
@ -204,6 +211,7 @@ public class DeviceCommunicationService extends Service {
if (pair) {
deviceSupport.pair();
} else {
deviceSupport.setAutoReconnect(autoReconnect);
deviceSupport.connect();
}
} else {
@ -241,12 +249,12 @@ public class DeviceCommunicationService extends Service {
if (((notificationSpec.flags & NotificationSpec.FLAG_WEARABLE_REPLY) > 0)
|| (notificationSpec.type == NotificationType.SMS && notificationSpec.phoneNumber != null)) {
// NOTE: maybe not where it belongs
if (sharedPrefs.getBoolean("pebble_force_untested", false)) {
if (prefs.getBoolean("pebble_force_untested", false)) {
// I would rather like to save that as an array in ShadredPreferences
// this would work but I dont know how to do the same in the Settings Activity's xml
ArrayList<String> replies = new ArrayList<>();
for (int i = 1; i <= 16; i++) {
String reply = sharedPrefs.getString("canned_reply_" + i, null);
String reply = prefs.getString("canned_reply_" + i, null);
if (reply != null && !reply.equals("")) {
replies.add(reply);
}
@ -479,6 +487,10 @@ public class DeviceCommunicationService extends Service {
@Override
public void onDestroy() {
if (hasPrefs()) {
getPrefs().getPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
LOG.debug("DeviceCommunicationService is being destroyed");
super.onDestroy();
@ -515,4 +527,26 @@ public class DeviceCommunicationService extends Service {
return name;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (GBPrefs.AUTO_RECONNECT.equals(key)) {
boolean autoReconnect = getGBPrefs().getAutoReconnect();
if (mDeviceSupport != null) {
mDeviceSupport.setAutoReconnect(autoReconnect);
}
}
}
protected boolean hasPrefs() {
return getPrefs().getPreferences() != null;
}
public Prefs getPrefs() {
return GBApplication.getPrefs();
}
public GBPrefs getGBPrefs() {
return GBApplication.getGBPrefs();
}
}

View File

@ -62,6 +62,20 @@ public interface DeviceSupport extends EventHandler {
*/
boolean useAutoConnect();
/**
* Configures this instance to automatically attempt to reconnect after a connection loss.
* How, how long, or how often is up to the implementation.
* Note that tome implementations may not support automatic reconnection at all.
* @param enable
*/
void setAutoReconnect(boolean enable);
/**
* Returns whether this instance to configured to automatically attempt to reconnect after a
* connection loss.
*/
boolean getAutoReconnect();
/**
* Attempts to pair and connect this device with the gadget device. Success
* will be reported via a device change Intent.

View File

@ -56,6 +56,16 @@ public class ServiceDeviceSupport implements DeviceSupport {
return delegate.connect();
}
@Override
public void setAutoReconnect(boolean enable) {
delegate.setAutoReconnect(enable);
}
@Override
public boolean getAutoReconnect() {
return delegate.getAutoReconnect();
}
@Override
public void dispose() {
delegate.dispose();

View File

@ -42,10 +42,19 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
public boolean connect() {
if (mQueue == null) {
mQueue = new BtLEQueue(getBluetoothAdapter(), getDevice(), this, getContext());
mQueue.setAutoReconnect(getAutoReconnect());
}
return mQueue.connect();
}
@Override
public void setAutoReconnect(boolean enable) {
super.setAutoReconnect(enable);
if (mQueue != null) {
mQueue.setAutoReconnect(enable);
}
}
/**
* Subclasses should populate the given builder to initialize the device (if necessary).
*

View File

@ -34,12 +34,6 @@ public final class BtLEQueue {
private final GBDevice mGbDevice;
private final BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
/**
* When an automatic reconnect was attempted after a connection breakdown (error)
*/
private long lastReconnectTime = System.currentTimeMillis();
private static final long MIN_MILLIS_BEFORE_RECONNECT = 1000 * 60 * 5; // 5 minutes
private final BlockingQueue<Transaction> mTransactions = new LinkedBlockingQueue<>();
private volatile boolean mDisposed;
@ -51,6 +45,7 @@ public final class BtLEQueue {
private CountDownLatch mConnectionLatch;
private BluetoothGattCharacteristic mWaitCharacteristic;
private final InternalGattCallback internalGattCallback;
private boolean mAutoReconnect;
private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") {
@ -130,6 +125,10 @@ public final class BtLEQueue {
dispatchThread.start();
}
public void setAutoReconnect(boolean enable) {
mAutoReconnect = enable;
}
protected boolean isConnected() {
return mGbDevice.isConnected();
}
@ -222,11 +221,9 @@ public final class BtLEQueue {
* @return true if a reconnection attempt was made, or false otherwise
*/
private boolean maybeReconnect() {
long currentTime = System.currentTimeMillis();
if (currentTime - lastReconnectTime >= MIN_MILLIS_BEFORE_RECONNECT) {
LOG.info("Automatic reconnection attempt...");
lastReconnectTime = currentTime;
return connect();
if (mAutoReconnect && mBluetoothGatt != null) {
LOG.info("Enabling automatic ble reconnect...");
return mBluetoothGatt.connect();
}
return false;
}

View File

@ -3,9 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;
@ -21,6 +19,7 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
@ -52,6 +51,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.Fe
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.UpdateFirmwareOperation;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_FLASH_COLOUR;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_FLASH_COUNT;
@ -422,7 +422,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
private void performPreferredNotification(String task, String notificationOrigin, BtLEAction extraAction) {
try {
TransactionBuilder builder = performInitialized(task);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
Prefs prefs = GBApplication.getPrefs();
int vibrateDuration = getPreferredVibrateDuration(notificationOrigin, prefs);
int vibratePause = getPreferredVibratePause(notificationOrigin, prefs);
short vibrateTimes = getPreferredVibrateCount(notificationOrigin, prefs);
@ -441,35 +441,35 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
}
private int getPreferredFlashDuration(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredFlashDuration(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(FLASH_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_DURATION);
}
private int getPreferredOriginalColour(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredOriginalColour(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(FLASH_ORIGINAL_COLOUR, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_ORIGINAL_COLOUR);
}
private int getPreferredFlashColour(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredFlashColour(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(FLASH_COLOUR, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_COLOUR);
}
private int getPreferredFlashCount(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredFlashCount(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(FLASH_COUNT, notificationOrigin, prefs, DEFAULT_VALUE_FLASH_COUNT);
}
private int getPreferredVibratePause(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredVibratePause(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(VIBRATION_PAUSE, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_PAUSE);
}
private short getPreferredVibrateCount(String notificationOrigin, SharedPreferences prefs) {
private short getPreferredVibrateCount(String notificationOrigin, Prefs prefs) {
return (short) Math.min(Short.MAX_VALUE, getNotificationPrefIntValue(VIBRATION_COUNT, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_COUNT));
}
private int getPreferredVibrateDuration(String notificationOrigin, SharedPreferences prefs) {
private int getPreferredVibrateDuration(String notificationOrigin, Prefs prefs) {
return getNotificationPrefIntValue(VIBRATION_DURATION, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_DURATION);
}
private VibrationProfile getPreferredVibrateProfile(String notificationOrigin, SharedPreferences prefs, short repeat) {
private VibrationProfile getPreferredVibrateProfile(String notificationOrigin, Prefs prefs, short repeat) {
String profileId = getNotificationPrefStringValue(VIBRATION_PROFILE, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_PROFILE);
return VibrationProfile.getProfile(profileId, repeat);
}
@ -1031,8 +1031,8 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
TransactionBuilder builder = performInitialized("Send upcoming events");
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
int availableSlots = Integer.parseInt(prefs.getString(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, "0"));
Prefs prefs = GBApplication.getPrefs();
int availableSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
if (availableSlots > 0) {
CalendarEvents upcomingEvents = new CalendarEvents();

View File

@ -2,9 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.preference.PreferenceManager;
import android.widget.Toast;
import org.slf4j.Logger;
@ -32,6 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAc
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
//import java.util.concurrent.Executors;
//import java.util.concurrent.ScheduledExecutorService;
@ -365,7 +364,7 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
*/
private void sendAckDataTransfer(Calendar time, int bytesTransferred) {
byte[] ackTime = MiBandDateConverter.calendarToRawBytes(time);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
Prefs prefs = GBApplication.getPrefs();
byte[] ackChecksum = new byte[]{
(byte) (bytesTransferred & 0xff),

View File

@ -8,10 +8,8 @@ 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.os.ParcelUuid;
import android.preference.PreferenceManager;
import org.json.JSONArray;
import org.json.JSONException;
@ -29,6 +27,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
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;
@ -44,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class PebbleIoThread extends GBDeviceIoThread {
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
@ -62,7 +62,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
public static final String PEBBLEKIT_ACTION_APP_START = "com.getpebble.action.app.START";
public static final String PEBBLEKIT_ACTION_APP_STOP = "com.getpebble.action.app.STOP";
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
final Prefs prefs = GBApplication.getPrefs();
private final PebbleProtocol mPebbleProtocol;
private final PebbleSupport mPebbleSupport;
@ -160,7 +160,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
mPebbleProtocol = (PebbleProtocol) gbDeviceProtocol;
mBtAdapter = btAdapter;
mPebbleSupport = pebbleSupport;
mEnablePebblekit = sharedPrefs.getBoolean("pebble_enable_pebblekit", false);
mEnablePebblekit = prefs.getBoolean("pebble_enable_pebblekit", false);
}
@Override
@ -199,7 +199,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
return false;
}
mPebbleProtocol.setForceProtocol(sharedPrefs.getBoolean("pebble_force_protocol", false));
mPebbleProtocol.setForceProtocol(prefs.getBoolean("pebble_force_protocol", false));
mIsConnected = true;
if (originalState == GBDevice.State.WAITING_FOR_RECONNECT) {
@ -364,8 +364,8 @@ public class PebbleIoThread extends GBDeviceIoThread {
if (e.getMessage().contains("socket closed")) { //FIXME: this does not feel right
LOG.info(e.getMessage());
mIsConnected = false;
int reconnectAttempts = Integer.valueOf(sharedPrefs.getString("pebble_reconnect_attempts", "10"));
if (reconnectAttempts > 0) {
int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
if (GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
gbDevice.setState(GBDevice.State.CONNECTING);
gbDevice.sendDeviceUpdateIntent(getContext());
int delaySeconds = 1;
@ -480,7 +480,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
private boolean evaluateGBDeviceEventPebble(GBDeviceEvent deviceEvent) {
if (deviceEvent instanceof GBDeviceEventVersionInfo) {
if (sharedPrefs.getBoolean("datetime_synconconnect", true)) {
if (prefs.getBoolean("datetime_synconconnect", true)) {
LOG.info("syncing time");
write(mPebbleProtocol.encodeSetTime());
}

View File

@ -3,16 +3,16 @@ package nodomain.freeyourgadget.gadgetbridge.service.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.view.KeyEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class GBMusicControlReceiver extends BroadcastReceiver {
private static final Logger LOG = LoggerFactory.getLogger(GBMusicControlReceiver.class);
@ -53,8 +53,8 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
}
if (keyCode != -1) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
String audioPlayer = sharedPrefs.getString("audio_player", "default");
Prefs prefs = GBApplication.getPrefs();
String audioPlayer = prefs.getString("audio_player", "default");
long eventtime = SystemClock.uptimeMillis();

View File

@ -3,8 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.util;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.widget.Toast;
import java.util.ArrayList;
@ -12,6 +10,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
@ -75,8 +74,8 @@ public class DeviceHelper {
}
}
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
String miAddr = sharedPrefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
Prefs prefs = GBApplication.getPrefs();
String miAddr = prefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
if (miAddr.length() > 0) {
GBDevice miDevice = new GBDevice(miAddr, "MI", DeviceType.MIBAND);
if (!availableDevices.contains(miDevice)) {
@ -84,8 +83,8 @@ public class DeviceHelper {
}
}
String pebbleEmuAddr = sharedPrefs.getString("pebble_emu_addr", "");
String pebbleEmuPort = sharedPrefs.getString("pebble_emu_port", "");
String pebbleEmuAddr = prefs.getString("pebble_emu_addr", "");
String pebbleEmuPort = prefs.getString("pebble_emu_port", "");
if (pebbleEmuAddr.length() >= 7 && pebbleEmuPort.length() > 0) {
GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", DeviceType.PEBBLE);
availableDevices.add(pebbleEmuDevice);

View File

@ -0,0 +1,16 @@
package nodomain.freeyourgadget.gadgetbridge.util;
public class GBPrefs {
public static final String AUTO_RECONNECT = "general_autocreconnect";
public static boolean AUTO_RECONNECT_DEFAULT = true;
private final Prefs mPrefs;
public GBPrefs(Prefs prefs) {
mPrefs = prefs;
}
public boolean getAutoReconnect() {
return mPrefs.getBoolean(AUTO_RECONNECT, AUTO_RECONNECT_DEFAULT);
}
}

View File

@ -0,0 +1,149 @@
package nodomain.freeyourgadget.gadgetbridge.util;
import android.content.SharedPreferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
/**
* Wraps SharedPreferences to avoid ClassCastExceptions and others.
*/
public class Prefs {
private static final Logger LOG = LoggerFactory.getLogger(Prefs.class);
private final SharedPreferences preferences;
public Prefs(SharedPreferences preferences) {
this.preferences = preferences;
}
public String getString(String key, String defaultValue) {
String value = preferences.getString(key, defaultValue);
if (value == null || "".equals(value)) {
return defaultValue;
}
return value;
}
public Set<String> getStringSet(String key, Set<String> defaultValue) {
Set<String> value = preferences.getStringSet(key, defaultValue);
if (value == null || value.isEmpty()) {
return defaultValue;
}
return value;
}
/**
* Returns the preference saved under the given key as an integer value.
* Note that it is irrelevant whether the preference value was actually
* saved as an integer value or a string value.
* @param key the preference key
* @param defaultValue the default value to return if the preference value is unset
* @return the saved preference value or the given defaultValue
*/
public int getInt(String key, int defaultValue) {
try {
return preferences.getInt(key, defaultValue);
} catch (Exception ex) {
try {
String value = preferences.getString(key, String.valueOf(defaultValue));
if ("".equals(value)) {
return defaultValue;
}
return Integer.parseInt(value);
} catch (Exception ex2) {
logReadError(key, ex);
return defaultValue;
}
}
}
/**
* Returns the preference saved under the given key as a long value.
* Note that it is irrelevant whether the preference value was actually
* saved as a long value or a string value.
* @param key the preference key
* @param defaultValue the default value to return if the preference value is unset
* @return the saved preference value or the given defaultValue
*/
public long getLong(String key, long defaultValue) {
try {
return preferences.getLong(key, defaultValue);
} catch (Exception ex) {
try {
String value = preferences.getString(key, String.valueOf(defaultValue));
if ("".equals(value)) {
return defaultValue;
}
return Long.parseLong(value);
} catch (Exception ex2) {
logReadError(key, ex);
return defaultValue;
}
}
}
/**
* Returns the preference saved under the given key as a float value.
* Note that it is irrelevant whether the preference value was actually
* saved as a float value or a string value.
* @param key the preference key
* @param defaultValue the default value to return if the preference value is unset
* @return the saved preference value or the given defaultValue
*/
public float getFloat(String key, float defaultValue) {
try {
return preferences.getFloat(key, defaultValue);
} catch (Exception ex) {
try {
String value = preferences.getString(key, String.valueOf(defaultValue));
if ("".equals(value)) {
return defaultValue;
}
return Float.parseFloat(value);
} catch (Exception ex2) {
logReadError(key, ex);
return defaultValue;
}
}
}
/**
* Returns the preference saved under the given key as a boolean value.
* Note that it is irrelevant whether the preference value was actually
* saved as a boolean value or a string value.
* @param key the preference key
* @param defaultValue the default value to return if the preference value is unset
* @return the saved preference value or the given defaultValue
*/
public boolean getBoolean(String key, boolean defaultValue) {
try {
return preferences.getBoolean(key, defaultValue);
} catch (Exception ex) {
try {
String value = preferences.getString(key, String.valueOf(defaultValue));
if ("".equals(value)) {
return defaultValue;
}
return Boolean.parseBoolean(value);
} catch (Exception ex2) {
logReadError(key, ex);
return defaultValue;
}
}
}
private void logReadError(String key, Exception ex) {
LOG.error("Error reading preference value: " + key + "; returning default value", ex); // log the first exception
}
/**
* Access to the underlying SharedPreferences, typically only used for editing values.
* @return the underlying SharedPreferences object.
*/
public SharedPreferences getPreferences() {
return preferences;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

View File

@ -41,7 +41,7 @@
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_gravity="bottom|end"
android:src="@drawable/ic_add_black"
android:src="@drawable/ic_add_white"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
android:layout_marginBottom="10dp"

View File

@ -70,7 +70,7 @@
<string name="this_is_a_test_notification_from_gadgetbridge">Dies ist eine Test Benachrichtigung von Gadgetbridge</string>
<string name="bluetooth_is_not_supported_">Bluetooth wird nicht unterstützt.</string>
<string name="bluetooth_is_disabled_">Bluetooth ist abgeschaltet.</string>
<string name="tap_connected_device_for_app_mananger">berühre das verbundene Gerät, um den App Mananger zu starten</string>
<string name="tap_connected_device_for_app_mananger">berühre das verbundene Gerät, um den App Manager zu starten</string>
<string name="tap_a_device_to_connect">berühre ein Gerät zum Verbinden</string>
<string name="cannot_connect_bt_address_invalid_">Verbindung kann nicht aufgebaut werden. BT Adresse ungültig?</string>
<string name="gadgetbridge_running">Gadgetbridge läuft</string>
@ -102,13 +102,13 @@
<string name="miband_pairing_using_dummy_userdata">Keine gültigen Benutzerinformationen angegeben, verwende Dummy-Daten für\'s Erste.</string>
<string name="miband_pairing_tap_hint">Wenn Dein Mi Band vibriert und blinkt, tippe ein paar Mal schnell hintereinander darauf.</string>
<string name="appinstaller_install">Installieren</string>
<string name="discovery_connected_devices_hint">Mach Dein Gerät auffindbar. Derzeit verbundene Geräte sind in der Regel nicht auffindbar.</string>
<string name="discovery_connected_devices_hint">Mach Dein Gerät auffindbar. Derzeit verbundene Geräte sind in der Regel nicht auffindbar. Wenn Dein Gerät nach zwei Minuten nicht angezeigt wird, versuche es nach einem Neustart Deines Telefons noch einmal. </string>
<string name="discovery_note">Tipp:</string>
<string name="candidate_item_device_image">Bild des Geräts</string>
<string name="miband_prefs_alias">Name/Alias</string>
<string name="pref_header_vibration_count">Anzahl der Vibrationen</string>
<string name="title_activity_sleepmonitor">Schlafmonitor</string>
<string name="pref_write_logfiles">Log-Dateien schreiben (Neustart erforderlich)</string>
<string name="pref_write_logfiles">Log-Dateien schreiben</string>
<string name="initializing">initialisiere</string>
<string name="busy_task_fetch_activity_data">Hole Aktivitätsdaten</string>
<string name="sleep_activity_date_range">Von %1$s bis %2$s</string>

View File

@ -107,7 +107,7 @@
<string name="miband_prefs_alias">Nombre/Apodo</string>
<string name="pref_header_vibration_count">Número de vibraciones</string>
<string name="title_activity_sleepmonitor">Monitor de sueño</string>
<string name="pref_write_logfiles">Guardar logs (requiere reiniciar)</string>
<string name="pref_write_logfiles">Guardar logs</string>
<string name="initializing">iniciando</string>
<string name="busy_task_fetch_activity_data">Recuperando datos de actividad</string>
<string name="sleep_activity_date_range">Desde %1$s a %2$s</string>

View File

@ -71,7 +71,7 @@
<string name="bluetooth_is_not_supported_">Le Bluetooth n\'est pas supporté.</string>
<string name="bluetooth_is_disabled_">Le Bluetooth est désactivé.</string>
<string name="tap_connected_device_for_app_mananger">Cliquez sur l\'appareil pour le connecter au gestionnaire d\'application</string>
<string name="tap_a_device_to_connect">Cliquez sur l\'appareil pour le connecter</string>
<string name="tap_a_device_to_connect">Tapotter sur le périphérique pour le connecter.</string>
<string name="cannot_connect_bt_address_invalid_">Connexion impossible. Ladresse Bluetooth est-elle invalide? </string>
<string name="gadgetbridge_running">Gadgetbridge est en fonctionnement</string>
<string name="installing_binary_d_d">Installation du binaire %1$d/%2$d</string>
@ -102,13 +102,12 @@
<string name="miband_pairing_using_dummy_userdata">Aucune donnée utilisateur valide fournie, utilisation de données fictives pour le moment</string>
<string name="miband_pairing_tap_hint">Quand votre Mi Band vibre et clignote, appuyez dessus plusieurs fois d\'affilée.</string>
<string name="appinstaller_install">Installer</string>
<string name="discovery_connected_devices_hint">Rendez votre appareil découvrable. Les appareils déjà connectés ne seront pas découverts.</string>
<string name="discovery_connected_devices_hint">Rendre votre montre découvrable. Pour l\'instant les appareils connectés ne seront probablement pas découvert. Si votre montre napparaît pas après 2 minutes, essayer à nouveau après avoir redémarré.</string>
<string name="discovery_note">Note:</string>
<string name="candidate_item_device_image">Image de l\'appareil</string>
<string name="miband_prefs_alias">Nom/Pseudo</string>
<string name="pref_header_vibration_count">Nombre de vibrations</string>
<string name="title_activity_sleepmonitor">Moniteur de sommeil</string>
<string name="pref_write_logfiles">Écrire les fichiers journaux (redémarrage requis)</string>
<string name="initializing">Initialisation</string>
<string name="busy_task_fetch_activity_data">Récupération des données d\'activité</string>
<string name="sleep_activity_date_range">De %1$s à %2$s</string>
@ -197,6 +196,7 @@
<string name="miband_fwinstaller_incompatible_version">Micrologiciel non compatible</string>
<string name="fwinstaller_firmware_not_compatible_to_device">Ce micrologiciel n\'est pas compatible avec l\'appareil</string>
<string name="miband_prefs_reserve_alarm_calendar">Alarmes à réserver pour événements futurs</string>
<string name="miband_prefs_hr_sleep_detection">Utiliser le capteur cardiaque pour améliorer la précision du sommeil</string>
<string name="waiting_for_reconnect">en attente de reconnexion</string>
<string name="appmananger_app_reinstall">Réinstaller</string>
<string name="activity_prefs_about_you">A propos de vous</string>
@ -211,4 +211,14 @@
<string name="app_configure">Configurer</string>
<string name="appwidget_text">ZzZz</string>
<string name="add_widget">Ajouter un widget</string>
<string name="activity_prefs_sleep_duration">Préférer le mode heure pendant le sommeil</string>
<string name="appwidget_alarms_set">Une alarme a été enregistré pour %1$02d:%2$02d</string>
<string name="device_hw">Modèle: %1$s</string>
<string name="device_fw">Micrologiciel: %1$s</string>
<string name="error_creating_directory_for_logfiles">Erreur à la création de votre fichier log : %1$s</string>
<string name="DEVINFO_HR_VER">HR:</string>
<string name="updatefirmwareoperation_update_in_progress">Le firmware se met à jour</string>
<string name="updatefirmwareoperation_firmware_not_sent">Échec lors de l\'écriture du micrologiciel</string>
<string name="charts_legend_heartrate">Rythme cardiaque</string>
<string name="live_activity_heart_rate">Rythme cardiaque</string>
</resources>

View File

@ -108,7 +108,7 @@
<string name="miband_prefs_alias">Nome / Soprannome</string>
<string name="pref_header_vibration_count">Numero vibrazioni</string>
<string name="title_activity_sleepmonitor">Monitoraggio del sonno</string>
<string name="pref_write_logfiles">Salva il log su file (richiede riavvio)</string>
<string name="pref_write_logfiles">Salva il log su file</string>
<string name="initializing">inizializzazione in corso</string>
<string name="busy_task_fetch_activity_data">Recupero dati attività</string>
<string name="sleep_activity_date_range">Da %1$s a %2$s</string>

View File

@ -32,6 +32,9 @@
<string name="pref_header_datetime">日付と時刻</string>
<string name="pref_title_datetime_syctimeonconnect">時間を合わせる</string>
<string name="pref_summary_datetime_syctimeonconnect">接続したとき、Androidで時間またはタイムゾーンを変更したときに、デバイスに時間を同期</string>
<string name="pref_title_theme">テーマ</string>
<string name="pref_theme_light">ライト</string>
<string name="pref_theme_dark">ダーク</string>
<string name="pref_header_notifications">通知</string>
<string name="pref_title_notifications_repetitions">繰り返し</string>
<string name="pref_title_notifications_call">電話通知</string>
@ -108,7 +111,7 @@
<string name="miband_prefs_alias">名前/別名</string>
<string name="pref_header_vibration_count">バイブレーション回数</string>
<string name="title_activity_sleepmonitor">睡眠観測</string>
<string name="pref_write_logfiles">ログファイルを出力 (再起動が必要)</string>
<string name="pref_write_logfiles">ログファイルを出力</string>
<string name="initializing">初期化中</string>
<string name="busy_task_fetch_activity_data">活動データを取得中</string>
<string name="sleep_activity_date_range">%1$sから%2$sまで</string>
@ -220,4 +223,6 @@
<string name="DEVINFO_HR_VER">HR: </string>
<string name="updatefirmwareoperation_update_in_progress">ファームウェアを更新しています</string>
<string name="updatefirmwareoperation_firmware_not_sent">ファームウェアを送信しませんでした</string>
<string name="charts_legend_heartrate">心拍数</string>
<string name="live_activity_heart_rate">心拍数</string>
</resources>

View File

@ -19,6 +19,7 @@
<!--Strings related to FwAppInstaller-->
<string name="title_activity_fw_app_insaller">펌웨어/앱 설치</string>
<string name="fw_upgrade_notice">지금 기존의 Mi Band 펌웨어 대신 %s 펌웨어를 설치하려고 합니다.</string>
<string name="fw_multi_upgrade_notice">지금 Mi Band의 기존 펌웨어 대신 %1$s와 %2$s 펌웨어를 설치하려고 합니다.</string>
<string name="miband_firmware_known">이 펌웨어는 테스트를 거쳤고 가젯브릿지와 호환됩니다.</string>
<string name="miband_firmware_unknown_warning">이 펌웨어는 테스트를 거치지 않았고 가젯브릿지와 호환되지 않을 수 있습니다.\n\n Mi Band에 설치하지 않는 것이 좋습니다.</string>
<string name="miband_firmware_suggest_whitelist">여전히 계속 진행하기를 원하고 이후에도 정상적으로 작동하기를 원한다면, %s 화이트리스트 펌웨어 버전을 가젯브릿지 개발자들에게 알려주세요.</string>
@ -31,6 +32,9 @@
<string name="pref_header_datetime">날짜와 시간</string>
<string name="pref_title_datetime_syctimeonconnect">시간 동기화</string>
<string name="pref_summary_datetime_syctimeonconnect">시간이 바뀌거나, 시간대가 바뀌거나, 접속을 할 때 기기와 시간을 동기화</string>
<string name="pref_title_theme">테마</string>
<string name="pref_theme_light">밝음</string>
<string name="pref_theme_dark">어두움</string>
<string name="pref_header_notifications">알림</string>
<string name="pref_title_notifications_repetitions">반복</string>
<string name="pref_title_notifications_call">전화</string>
@ -48,6 +52,7 @@
<string name="pref_header_development">개발자 옵션</string>
<string name="pref_title_development_miaddr">Mi Band 주소</string>
<string name="pref_title_pebble_settings">Pebble 설정</string>
<string name="pref_title_pebble_activitytracker">선호하는 액티비티 트래커</string>
<string name="pref_title_enable_pebblekit">제3자 안드로이드 앱 접근을 허용</string>
<string name="pref_summary_enable_pebblekit">PebbleKit을 사용하는 안드로이드 앱을 실험적으로 지원</string>
<string name="pref_title_pebble_forceprotocol">강제 알림 프로토콜</string>
@ -99,13 +104,13 @@
<string name="miband_pairing_using_dummy_userdata">올바르지 않은 사용자 정보입니다. 일단 임시 사용자 정보를 사용합니다.</string>
<string name="miband_pairing_tap_hint">Mi Band가 진동하고 깜빡일 때, 연달아 몇 번 두드리세요.</string>
<string name="appinstaller_install">설치</string>
<string name="discovery_connected_devices_hint">기기를 발견 가능하도록 설정하세요. 현재 연결된 기기들은 발견될 수 없습니다.</string>
<string name="discovery_connected_devices_hint">기기를 발견 가능하도록 설정하세요. 현재 연결된 기기들은 발견될 수 없습니다. 2분이 지나도 기기가 나타나지 않는다면 재부팅 후 다시 시도해보세요.</string>
<string name="discovery_note">알림: </string>
<string name="candidate_item_device_image">기기 이미지</string>
<string name="miband_prefs_alias">이름/별명</string>
<string name="pref_header_vibration_count">진동 횟수</string>
<string name="title_activity_sleepmonitor">수면 측정계</string>
<string name="pref_write_logfiles">기록 파일 작성 (재시작 필요)</string>
<string name="pref_write_logfiles">기록 파일 작성</string>
<string name="initializing">초기화 중</string>
<string name="busy_task_fetch_activity_data">활동 데이터 가져오는 중</string>
<string name="sleep_activity_date_range">%1$s에서 %2$s(으)로</string>
@ -194,6 +199,7 @@
<string name="miband_fwinstaller_incompatible_version">호환되지 않는 펌웨어</string>
<string name="fwinstaller_firmware_not_compatible_to_device">이 펌웨어는 기기와 호환되지 않습니다</string>
<string name="miband_prefs_reserve_alarm_calendar">다가오는 이벤트를 위해 예약할 알람</string>
<string name="miband_prefs_hr_sleep_detection">수면 측정을 향상시키기 위해 심박 센서 사용</string>
<string name="waiting_for_reconnect">재접속을 기다리는 중</string>
<string name="appmananger_app_reinstall">재설치</string>
<string name="activity_prefs_about_you">당신에 대해</string>
@ -201,4 +207,21 @@
<string name="activity_prefs_gender">성별</string>
<string name="activity_prefs_height_cm">키 (cm)</string>
<string name="activity_prefs_weight_kg">몸무게 (kg)</string>
<string name="appmanager_health_activate">활성화</string>
<string name="appmanager_health_deactivate">비활성화</string>
<string name="authenticating">인증 중</string>
<string name="authentication_required">인증 필요</string>
<string name="app_configure">설정</string>
<string name="appwidget_text">Zzz</string>
<string name="add_widget">위젯 추가</string>
<string name="activity_prefs_sleep_duration">선호하는 수면 시간</string>
<string name="appwidget_alarms_set">%1$02d:%2$02d 알람이 설정되었습니다</string>
<string name="device_hw">하드웨어: %1$s</string>
<string name="device_fw">펌웨어: %1$s</string>
<string name="error_creating_directory_for_logfiles">기록 파일을 저장할 디렉토리 생성 오류: %1$s</string>
<string name="DEVINFO_HR_VER">심박수:</string>
<string name="updatefirmwareoperation_update_in_progress">펌웨어 업데이트 진행 중</string>
<string name="updatefirmwareoperation_firmware_not_sent">펌웨어가 전송되지 않음</string>
<string name="charts_legend_heartrate">심박수</string>
<string name="live_activity_heart_rate">심박수</string>
</resources>

View File

@ -105,7 +105,7 @@
<string name="miband_prefs_alias">Nazwisko/Pseudonim</string>
<string name="pref_header_vibration_count">Liczba wibracji</string>
<string name="title_activity_sleepmonitor">Monitor snu</string>
<string name="pref_write_logfiles">Zapisuj logi (wymaga restartu)</string>
<string name="pref_write_logfiles">Zapisuj logi</string>
<string name="initializing">Uruchamianie</string>
<string name="busy_task_fetch_activity_data">Pobieranie danych aktywności</string>
<string name="sleep_activity_date_range">Od %1$s do %2$s</string>

View File

@ -12,7 +12,7 @@
<string name="controlcenter_disconnect">Отключиться</string>
<string name="title_activity_debug">Отладка</string>
<!--Strings related to AppManager-->
<string name="title_activity_appmanager">App Mananger</string>
<string name="title_activity_appmanager">App Manager</string>
<string name="appmananger_app_delete">Удалить</string>
<!--Strings related to AppBlacklist-->
<string name="title_activity_appblacklist">Заблокированные уведомления</string>
@ -68,7 +68,7 @@
<string name="this_is_a_test_notification_from_gadgetbridge">Это тестовое уведомление от Gadgetbridge</string>
<string name="bluetooth_is_not_supported_">Bluetooth не поддерживается.</string>
<string name="bluetooth_is_disabled_">Bluetooth отключён.</string>
<string name="tap_connected_device_for_app_mananger">нажмите на подключённое устройство для App Mananger</string>
<string name="tap_connected_device_for_app_mananger">нажмите на подключённое устройство для App Manager</string>
<string name="tap_a_device_to_connect">нажмите на устройство для соединения</string>
<string name="cannot_connect_bt_address_invalid_">Не удалось соединиться. Неверен адрес BT?</string>
<string name="gadgetbridge_running">Gadgetbridge запущен</string>
@ -106,7 +106,7 @@
<string name="miband_prefs_alias">Имя/псевдоним</string>
<string name="pref_header_vibration_count">Количество вибраций</string>
<string name="title_activity_sleepmonitor">Анализ сна</string>
<string name="pref_write_logfiles">Записывать файлы журнала (нужен перезапуск)</string>
<string name="pref_write_logfiles">Записывать файлы журнала</string>
<string name="initializing">Инициализация</string>
<string name="busy_task_fetch_activity_data">Получение данных активности</string>
<string name="sleep_activity_date_range">От %1$s до %2$s</string>

View File

@ -102,7 +102,7 @@
<string name="pref_header_vibration_count">Titreşim adedi</string>
<string name="title_activity_sleepmonitor">Uyku Monitörü</string>
<string name="pref_write_logfiles">Kütük dosyalarını yaz (yeniden başlatmak gerekir)</string>
<string name="pref_write_logfiles">Kütük dosyalarını yaz</string>
<string name="initializing">başlatılıyor</string>
<string name="busy_task_fetch_activity_data">Aktivite verisi alınıyor</string>

View File

@ -67,7 +67,7 @@
<string name="this_is_a_test_notification_from_gadgetbridge">Це тестове сповіщення від Gadgetbridge</string>
<string name="bluetooth_is_not_supported_">Bluetooth не підтримується.</string>
<string name="bluetooth_is_disabled_">Bluetooth вимкнуто.</string>
<string name="tap_connected_device_for_app_mananger">натисніть на під\'єднаний пристрій для App Mananger</string>
<string name="tap_connected_device_for_app_mananger">натисніть на під\'єднаний пристрій для App Manager</string>
<string name="tap_a_device_to_connect">натисніть на пристрій для з\'єднання</string>
<string name="cannot_connect_bt_address_invalid_">Не вдалося з\'єднатися. Можливо помилкова адреса BT?</string>
<string name="gadgetbridge_running">Gadgetbridge запущено</string>
@ -105,7 +105,7 @@
<string name="miband_prefs_alias">Ім\'я/нік</string>
<string name="pref_header_vibration_count">Кількість вібрацій</string>
<string name="title_activity_sleepmonitor">Аналіз сну</string>
<string name="pref_write_logfiles">Записувати файли звіту (потрібен перезапуск)</string>
<string name="pref_write_logfiles">Записувати файли звіту</string>
<string name="initializing">Ініціалізація…</string>
<string name="busy_task_fetch_activity_data">Отримання даних активності</string>
<string name="sleep_activity_date_range">Від %1$s до %2$s</string>

View File

@ -83,7 +83,7 @@
<string name="candidate_item_device_image">Ảnh thiết bị</string>
<string name="miband_prefs_alias">Tên/Bí danh</string>
<string name="title_activity_sleepmonitor">Trình giám sát giấc ngủ</string>
<string name="pref_write_logfiles">Ghi tập tin nhật ký (cần khởi động lại)</string>
<string name="pref_write_logfiles">Ghi tập tin nhật ký</string>
<string name="initializing">đang khởi chạy</string>
<string name="sleep_activity_date_range">Từ %1$s đến %2$s</string>
<string name="miband_prefs_wearside">Đeo bên trái hay phải?</string>

View File

@ -126,7 +126,7 @@
<string name="pref_header_vibration_count">Vibration Count</string>
<string name="title_activity_sleepmonitor">Sleep Monitor</string>
<string name="pref_write_logfiles">Write Log Files (needs restart)</string>
<string name="pref_write_logfiles">Write Log Files</string>
<string name="initializing">initializing</string>
<string name="busy_task_fetch_activity_data">Fetching Activity Data</string>
<string name="sleep_activity_date_range">From %1$s to %2$s</string>
@ -244,5 +244,6 @@
<string name="updatefirmwareoperation_firmware_not_sent">Firmware not sent</string>
<string name="charts_legend_heartrate">Heart Rate</string>
<string name="live_activity_heart_rate">Heart Rate</string>
<string name="pref_title_general_autocreonnect">Reconnect automatically</string>
</resources>

View File

@ -1,5 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
<release version="0.9.6" versioncode="50">
<change>Again some UI/theme improvements</change>
<change>New preference to reconnect after connection loss (defaults to true)</change>
<change>Fix crash when dealing with certain old preference values</change>
<change>Mi Band: automatically reconnect when back in range after connection loss</change>
<change>Mi Band 1S: display heart rate value again when invoked via the Debug view</change>
</release>
<release version="0.9.5" versioncode="49">
<change>Several UI Improvements</change>
<change>Easier First-time setup by using a FAB</change>
<change>Optional Dark Theme</change>
<change>Notification App Blacklist is now sorted</change>
<change>Gadgetbridge Icon in the notification bar displays connection state</change>
<change>Logging is now configurable without restart</change>
<change>Mi Band 1S: Initial live heartrate tracking</change>
<change>Fix certain crash in charts activity on slower devices (#277)</change>
</release>
<release version="0.9.4" versioncode="48">
<change>Fix crash in charts activities when changing the date, quickly (#277)</change>
<change>Pebble: support pebble health datalog messages of firmware 3.11 (this adds support for deep sleep!)</change>

View File

@ -79,7 +79,7 @@
android:defaultValue="60"
android:inputType="number"
android:key="mi_vibration_count_incoming_call"
android:maxLength="1"
android:maxLength="2"
android:title="@string/pref_title_notifications_repetitions" />
</PreferenceScreen>

View File

@ -7,6 +7,10 @@
android:defaultValue="false"
android:key="general_autoconnectonbluetooth"
android:title="@string/pref_title_general_autoconnectonbluetooth" />
<CheckBoxPreference
android:defaultValue="false"
android:key="general_autocreconnect"
android:title="@string/pref_title_general_autocreonnect" />
<ListPreference
android:defaultValue="default"
android:key="audio_player"

View File

@ -5,7 +5,9 @@ import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import junit.framework.Assert;
@ -22,7 +24,7 @@ public abstract class AbstractServiceTestCase<T extends Service> {
private final Class<T> mServiceClass;
private T mServiceInstance;
private Context mContext;
private Application mApplication;
private GBMockApplication mApplication;
private boolean wasStarted;
private PackageManager mPackageManager;
private NotificationManager mNotificationManager;
@ -41,6 +43,10 @@ public abstract class AbstractServiceTestCase<T extends Service> {
return mServiceInstance;
}
protected MockHelper getmMockHelper() {
return mMockHelper;
}
@Before
public void setUp() throws Exception {
mMockHelper = new MockHelper();
@ -69,7 +75,7 @@ public abstract class AbstractServiceTestCase<T extends Service> {
mServiceInstance = null;
}
protected Application createApplication(PackageManager packageManager) {
protected GBMockApplication createApplication(PackageManager packageManager) {
return new GBMockApplication(packageManager);
}
@ -85,9 +91,9 @@ public abstract class AbstractServiceTestCase<T extends Service> {
return new GBMockContext(application);
}
private T createService(Class<T> serviceClass, Application application, NotificationManager notificationManager) throws Exception {
protected T createService(Class<T> serviceClass, GBMockApplication application, NotificationManager notificationManager) throws Exception {
T service = mMockHelper.createService(serviceClass, application);
mMockHelper.addSystemServiceTo(service, Context.NOTIFICATION_SERVICE, getNotificationService());
mMockHelper.addSystemServiceTo(service, Context.NOTIFICATION_SERVICE, notificationManager);
return service;
}

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service;
import android.app.Application;
import android.app.NotificationManager;
import android.content.Context;
import org.junit.Before;
@ -11,6 +13,7 @@ import org.mockito.Mockito;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.test.GBMockApplication;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -41,6 +44,14 @@ public class DeviceCommunicationServiceTestCase extends AbstractServiceTestCase<
super(DeviceCommunicationService.class);
}
@Override
protected DeviceCommunicationService createService(Class<DeviceCommunicationService> serviceClass, GBMockApplication application, NotificationManager notificationManager) throws Exception {
DeviceCommunicationService service = getmMockHelper().createDeviceCommunicationService(serviceClass, application);
getmMockHelper().addSystemServiceTo(service, Context.NOTIFICATION_SERVICE, notificationManager);
return service;
}
@Before
public void setUp() throws Exception {
super.setUp();

View File

@ -1,18 +1,27 @@
package nodomain.freeyourgadget.gadgetbridge.test;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import android.test.mock.MockApplication;
import nodomain.freeyourgadget.gadgetbridge.GBEnvironment;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class GBMockApplication extends MockApplication {
private static final String PREF_NAME = "testprefs";
private final PackageManager mPackageManager;
private Prefs prefs;
private GBPrefs gbPrefs;
public GBMockApplication(PackageManager packageManager) {
GB.environment = GBEnvironment.createDeviceEnvironment().createLocalTestEnvironment();
mPackageManager = packageManager;
prefs = new Prefs(PreferenceManager.getDefaultSharedPreferences(this));
gbPrefs = new GBPrefs(prefs);
}
@Override
@ -25,4 +34,10 @@ public class GBMockApplication extends MockApplication {
return mPackageManager;
}
public Prefs getPrefs() {
return prefs;
}
public GBPrefs getGBPrefs() {
return gbPrefs;
}
}

View File

@ -11,6 +11,8 @@ import org.mockito.Mockito;
import java.lang.reflect.Constructor;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class MockHelper {
public <T extends Service> NotificationManager createNotificationManager(Context mContext) throws Exception {
Constructor<?>[] constructors = NotificationManager.class.getDeclaredConstructors();
@ -29,6 +31,13 @@ public class MockHelper {
return mockedService;
}
public <T extends DeviceCommunicationService> T createDeviceCommunicationService(Class<T> serviceClass, GBMockApplication application) throws Exception {
T mockedService = createService(serviceClass, application);
Mockito.when(mockedService.getPrefs()).thenReturn(application.getPrefs());
Mockito.when(mockedService.getGBPrefs()).thenReturn(application.getGBPrefs());
return mockedService;
}
public void addSystemServiceTo(Context context, String serviceName, Object service) {
Mockito.when(context.getSystemService(serviceName)).thenReturn(service);
}

View File

@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.android.tools.build:gradle:2.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files