diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dd79d2760..f15ef9079 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,6 +42,13 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".ControlCenter" /> + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SettingsActivity.java index 3254c986f..eac298401 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SettingsActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SettingsActivity.java @@ -1,6 +1,7 @@ package nodomain.freeyourgadget.gadgetbridge; import android.content.Intent; +import android.media.audiofx.BassBoost; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; @@ -10,12 +11,19 @@ import android.support.v4.app.NavUtils; import android.support.v4.content.LocalBroadcastManager; import android.view.MenuItem; -public class SettingsActivity extends PreferenceActivity { +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity; +import nodomain.freeyourgadget.gadgetbridge.miband.MiBandPreferencesActivity; + +public class SettingsActivity extends AbstractSettingsActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } + @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - getActionBar().setDisplayHomeAsUpEnabled(true); - addPreferencesFromResource(R.xml.preferences); Preference pref = (Preference) findPreference("notifications_generic"); pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @@ -25,9 +33,16 @@ public class SettingsActivity extends PreferenceActivity { return true; } }); - final Preference developmentMiaddr = findPreference(GB.PREF_DEVELOPMENT_MIBAND_ADDRESS); - bindPreferenceSummaryToValue(developmentMiaddr); + pref = (Preference) findPreference("pref_key_miband"); + pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + Intent enableIntent = new Intent(SettingsActivity.this, MiBandPreferencesActivity.class); + startActivity(enableIntent); + return true; + } + }); + final Preference developmentMiaddr = findPreference(GB.PREF_DEVELOPMENT_MIBAND_ADDRESS); developmentMiaddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { @@ -40,65 +55,8 @@ public class SettingsActivity extends PreferenceActivity { }); } - - /** - * A preference value change listener that updates the preference's summary - * to reflect its new value. - */ - private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - String stringValue = value.toString(); - - if (preference instanceof ListPreference) { - // For list preferences, look up the correct display value in - // the preference's 'entries' list. - ListPreference listPreference = (ListPreference) preference; - int index = listPreference.findIndexOfValue(stringValue); - - // Set the summary to reflect the new value. - preference.setSummary( - index >= 0 - ? listPreference.getEntries()[index] - : null); - - } else { - // For all other preferences, set the summary to the value's - // simple string representation. - preference.setSummary(stringValue); - } - return true; - } - }; - - /** - * Binds a preference's summary to its value. More specifically, when the - * preference's value is changed, its summary (line of text below the - * preference title) is updated to reflect the value. The summary is also - * immediately updated upon calling this method. The exact display format is - * dependent on the type of preference. - * - * @see #sBindPreferenceSummaryToValueListener - */ - private static void bindPreferenceSummaryToValue(Preference preference) { - // Set the listener to watch for value changes. - preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); - - // Trigger the listener immediately with the preference's - // current value. - sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, - PreferenceManager - .getDefaultSharedPreferences(preference.getContext()) - .getString(preference.getKey(), "")); - } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - return true; - } - return super.onOptionsItemSelected(item); + protected String[] getPreferenceKeysWithSummary() { + return new String[] { GB.PREF_DEVELOPMENT_MIBAND_ADDRESS }; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java new file mode 100644 index 000000000..da88e019a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractSettingsActivity.java @@ -0,0 +1,101 @@ +package nodomain.freeyourgadget.gadgetbridge.activities; + +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.support.v4.app.NavUtils; +import android.util.Log; +import android.view.MenuItem; + +public class AbstractSettingsActivity extends PreferenceActivity { + + private static final String TAG = "AbstractSettingsAct"; + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + getActionBar().setDisplayHomeAsUpEnabled(true); + + for (String prefKey : getPreferenceKeysWithSummary()) { + final Preference pref = findPreference(prefKey); + if (pref != null) { + bindPreferenceSummaryToValue(pref); + } else { + Log.e(TAG, "Unknown preference key: " + prefKey + ", unable to display value."); + } + } + } + + /** + * Subclasses should reimplement this to return the keys of those + * preferences which should print its values as a summary below the + * preference name. + */ + protected String[] getPreferenceKeysWithSummary() { + return new String[0]; + } + + /** + * A preference value change listener that updates the preference's summary + * to reflect its new value. + */ + private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + String stringValue = value.toString(); + + if (preference instanceof ListPreference) { + // For list preferences, look up the correct display value in + // the preference's 'entries' list. + ListPreference listPreference = (ListPreference) preference; + int index = listPreference.findIndexOfValue(stringValue); + + // Set the summary to reflect the new value. + preference.setSummary( + index >= 0 + ? listPreference.getEntries()[index] + : null); + + } else { + // For all other preferences, set the summary to the value's + // simple string representation. + preference.setSummary(stringValue); + } + return true; + } + }; + + /** + * Binds a preference's summary to its value. More specifically, when the + * preference's value is changed, its summary (line of text below the + * preference title) is updated to reflect the value. The summary is also + * immediately updated upon calling this method. The exact display format is + * dependent on the type of preference. + * + * @see #sBindPreferenceSummaryToValueListener + */ + private static void bindPreferenceSummaryToValue(Preference preference) { + // Set the listener to watch for value changes. + preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); + + // Trigger the listener immediately with the preference's + // current value. + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + PreferenceManager + .getDefaultSharedPreferences(preference.getContext()) + .getString(preference.getKey(), "")); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java new file mode 100644 index 000000000..6e99a6069 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java @@ -0,0 +1,10 @@ +package nodomain.freeyourgadget.gadgetbridge.miband; + +public interface MiBandConst { + + String PREF_USER_ALIAS = "mi_user_alias"; + String PREF_USER_YEAR_OF_BIRTH = "mi_user_year_of_birth"; + String PREF_USER_GENDER = "mi_user_gender"; + String PREF_USER_HEIGHT_CM = "mi_user_height_cm"; + String PREF_USER_WEIGHT_KG = "mi_user_weight_kg"; +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java new file mode 100644 index 000000000..6c55ac8eb --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandPreferencesActivity.java @@ -0,0 +1,30 @@ +package nodomain.freeyourgadget.gadgetbridge.miband; + +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceActivity; + +import nodomain.freeyourgadget.gadgetbridge.GB; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity; + +public class MiBandPreferencesActivity extends AbstractSettingsActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.miband_preferences); + } + + @Override + protected String[] getPreferenceKeysWithSummary() { + String[] prefsWithSummary = { + MiBandConst.PREF_USER_ALIAS, + MiBandConst.PREF_USER_YEAR_OF_BIRTH, + MiBandConst.PREF_USER_GENDER, + MiBandConst.PREF_USER_HEIGHT_CM, + MiBandConst.PREF_USER_WEIGHT_KG + }; + return prefsWithSummary; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java index fe0699fdc..524eeb158 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.miband; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; import java.io.IOException; @@ -10,6 +12,7 @@ import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBCommand; import nodomain.freeyourgadget.gadgetbridge.GBDevice.State; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.btle.TransactionBuilder; @@ -69,17 +72,30 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } private UserInfo getUserInfo() { - // SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext.getApplicationContext()); - // UserInfo mInfo = new UserInfo( - // mSharedPreferences.getString(MiBandConstants.PREFERENCE_MAC_ADDRESS, ""), - // "1550050550", - // (mSharedPreferences.getString(MiBandConstants.PREFERENCE_GENDER, "Male") == "Male") ? 1 : 0, - // Integer.parseInt(mSharedPreferences.getString(MiBandConstants.PREFERENCE_AGE, "25")), - // Integer.parseInt(mSharedPreferences.getString(MiBandConstants.PREFERENCE_HEIGHT, "175")), - // Integer.parseInt(mSharedPreferences.getString(MiBandConstants.PREFERENCE_WEIGHT, "60")), - // 0 - // ); - return UserInfo.getDefault(getDevice().getAddress()); + try { + SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext().getApplicationContext()); + int userYear = Integer.parseInt(mSharedPreferences.getString(MiBandConst.PREF_USER_YEAR_OF_BIRTH, "0")); + int age = 25; + if (userYear > 1900) { + age = Calendar.getInstance().get(Calendar.YEAR) - userYear; + if (age <= 0) { + age = 25; + } + } + UserInfo info = new UserInfo( + getDevice().getAddress(), + mSharedPreferences.getString(MiBandConst.PREF_USER_ALIAS, "1550050550"), + (mSharedPreferences.getString(MiBandConst.PREF_USER_GENDER, "male") == "male" ? 1 : 0), + age, + Integer.parseInt(mSharedPreferences.getString(MiBandConst.PREF_USER_HEIGHT_CM, "175")), + Integer.parseInt(mSharedPreferences.getString(MiBandConst.PREF_USER_WEIGHT_KG, "70")), + 0 + ); + return info; + } catch (Exception ex) { + Log.e(TAG, "Error creating user info from settings, using default user instead: " + ex); + return UserInfo.getDefault(getDevice().getAddress()); + } } /** diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/UserInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/UserInfo.java index 1ecc8412a..4f2aa11dc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/UserInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/UserInfo.java @@ -41,8 +41,8 @@ public class UserInfo { byte[] sequence = new byte[20]; - int uid = Integer.parseInt(alias); - + int uid = calculateUidFrom(alias); + String normalizedAlias = ensureTenCharacters(alias); sequence[0] = (byte) uid; sequence[1] = (byte) (uid >>> 8); sequence[2] = (byte) (uid >>> 16); @@ -55,7 +55,7 @@ public class UserInfo { sequence[8] = (byte) (type & 0xff); for (int u = 9; u < 19; u++) - sequence[u] = alias.getBytes()[u - 9]; + sequence[u] = normalizedAlias.getBytes()[u - 9]; byte[] crcSequence = new byte[19]; for (int u = 0; u < crcSequence.length; u++) @@ -66,6 +66,30 @@ public class UserInfo { this.data = sequence; } + private String ensureTenCharacters(String alias) { + char[] result = new char[10]; + int aliasLen = alias.length(); + int maxLen = Math.min(10, alias.length()); + int diff = 10 - maxLen; + for (int i = 0; i < maxLen; i++) { + result[i + diff] = alias.charAt(i); + } + for (int i = 0; i < diff; i++) { + result[i] = '0'; + } + return new String(result); + } + + private int calculateUidFrom(String alias) { + int uid = 0; + try { + uid = Integer.parseInt(alias); + } catch (NumberFormatException ex) { + uid = alias.hashCode(); // simple as that + } + return uid; + } + public byte[] getData() { return this.data; } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index c808fd1f2..7d88bcb66 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -11,4 +11,14 @@ never + + @string/male + @string/female + @string/other + + + male + female + other + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d070488bb..00a3c83b8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,4 +81,10 @@ Pair your Mi Band Pairing with %s… No mac address passed, cannot pair. + Device Specific Settings + Mi Band Settings + male + female + other + diff --git a/app/src/main/res/xml/miband_preferences.xml b/app/src/main/res/xml/miband_preferences.xml new file mode 100644 index 000000000..70c20af46 --- /dev/null +++ b/app/src/main/res/xml/miband_preferences.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index ca0024956..7ab3c00aa 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -52,6 +52,14 @@ android:title="@string/pref_title_whenscreenon" /> + + + +