From 1caca1439a699b5a5ca0da48b9758175df6050a9 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Wed, 24 Jun 2015 20:14:08 +0200 Subject: [PATCH 1/7] Initial implementation of setting alarms to the Mi Band. The code basically works, but there a lot of things to fix / improve. * The alarms are stored to and read from the Shared Preferences, but there is no persistence within the app (basically they are read and stored at every access) * The alarm list is not updated when coming back from the alarm detail view (probably related to the point above), but the actual alarm is * The alarms preference names is sometimes built by concatenating strings, which is not really safe * There is no check in the alarm constructor whether the stored string is a valid alarm representation * Even though only 3 alarms can be stored on the device, we could have more in the app and let the user choose which to sync * In the alarm detail view XML some material* drawables are used, it's possible that these break on android version < 5 * ... --- app/src/main/AndroidManifest.xml | 16 ++ .../BluetoothCommunicationService.java | 4 + .../gadgetbridge/ControlCenter.java | 7 + .../gadgetbridge/EventHandler.java | 2 + .../freeyourgadget/gadgetbridge/GBAlarm.java | 138 +++++++++++++++++ .../gadgetbridge/ServiceDeviceSupport.java | 8 + .../gadgetbridge/activities/AlarmDetails.java | 140 ++++++++++++++++++ .../activities/ConfigureAlarms.java | 55 +++++++ .../adapter/GBAlarmListAdapter.java | 99 +++++++++++++ .../gadgetbridge/miband/MiBandConst.java | 4 + .../gadgetbridge/miband/MiBandService.java | 5 +- .../gadgetbridge/miband/MiBandSupport.java | 38 +++++ .../gadgetbridge/pebble/PebbleSupport.java | 5 + .../res/layout/activity_alarm_details.xml | 123 +++++++++++++++ .../res/layout/activity_configure_alarms.xml | 16 ++ app/src/main/res/layout/alarm_item.xml | 109 ++++++++++++++ .../main/res/menu/controlcenter_context.xml | 3 + app/src/main/res/menu/menu_alarm_details.xml | 7 + app/src/main/res/menu/menu_set_alarm.xml | 7 + app/src/main/res/values/strings.xml | 12 +- 20 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java create mode 100644 app/src/main/res/layout/activity_alarm_details.xml create mode 100644 app/src/main/res/layout/activity_configure_alarms.xml create mode 100644 app/src/main/res/layout/alarm_item.xml create mode 100644 app/src/main/res/menu/menu_alarm_details.xml create mode 100644 app/src/main/res/menu/menu_set_alarm.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7df4110df..563016f89 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -194,6 +194,22 @@ android:name="android.support.PARENT_ACTIVITY" android:value="nodomain.freeyourgadget.gadgetbridge.ControlCenter" /> + + + + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java index e4d39b00e..74562d351 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java @@ -60,6 +60,7 @@ public class BluetoothCommunicationService extends Service { public static final String ACTION_FETCH_ACTIVITY_DATA = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.fetch_activity_data"; public static final String ACTION_DISCONNECT = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.disconnect"; public static final String ACTION_FIND_DEVICE = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.find_device"; + public static final String ACTION_SET_ALARMS = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.set_alarms"; public static final String EXTRA_PERFORM_PAIR = "perform_pair"; @@ -265,6 +266,9 @@ public class BluetoothCommunicationService extends Service { startForeground(GB.NOTIFICATION_ID, GB.createNotification(getString(R.string.gadgetbridge_running), this)); mStarted = true; break; + case ACTION_SET_ALARMS: + mDeviceSupport.onSetAlarms(); + } return START_STICKY; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java index c2f332782..22ca6ede9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; import nodomain.freeyourgadget.gadgetbridge.activities.ChartsActivity; import nodomain.freeyourgadget.gadgetbridge.activities.SleepChartActivity; import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapter; @@ -230,6 +231,12 @@ public class ControlCenter extends Activity { } }); } + case R.id.controlcenter_configure_alarms: + if (selectedDevice != null) { + Intent startIntent; + startIntent = new Intent(ControlCenter.this, ConfigureAlarms.class); + startActivity(startIntent); + } return true; case R.id.controlcenter_take_screenshot: if (selectedDevice != null) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java index 3f4e76533..29d7b1cce 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java @@ -13,6 +13,8 @@ public interface EventHandler { void onSetTime(long ts); + void onSetAlarms(); + void onSetCallState(String number, String name, GBCommand command); void onSetMusicInfo(String artist, String album, String track); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java new file mode 100644 index 000000000..8232423e6 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java @@ -0,0 +1,138 @@ +package nodomain.freeyourgadget.gadgetbridge; + +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import java.util.Calendar; + +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM_PREFIX; + +public class GBAlarm { + private int index; + private boolean enabled; + private boolean smartWakeup; + private int repetition; + private int hour; + private int minute; + + public static final byte ALARM_ONCE = 0; + public static final byte ALARM_MON = 1; + public static final byte ALARM_TUE = 2; + public static final byte ALARM_WED = 4; + public static final byte ALARM_THU = 8; + public static final byte ALARM_FRI = 16; + public static final byte ALARM_SAT = 32; + public static final byte ALARM_SUN = 64; + + public static final String DEFAULT_ALARM1 = "0,false,true,31,7,30"; + public static final String DEFAULT_ALARM2 = "1,false,false,96,8,00"; + public static final String DEFAULT_ALARM3 = "2,false,false,0,15,30"; + + public GBAlarm(int index, boolean enabled, boolean smartWakeup, byte repetition, int hour, int minute) { + this.index = index; + this.enabled = enabled; + this.smartWakeup = smartWakeup; + this.repetition = repetition; + this.hour = hour; + this.minute = minute; + store(); + } + + public GBAlarm(String fromPreferences){ + String[] tokens = fromPreferences.split(","); + //TODO: sanify the string! + this.index = Integer.parseInt(tokens[0]); + this.enabled = Boolean.parseBoolean(tokens[1]); + this.smartWakeup = Boolean.parseBoolean(tokens[2]); + this.repetition = Integer.parseInt(tokens[3]); + this.hour = Integer.parseInt(tokens[4]); + this.minute = Integer.parseInt(tokens[5]); + store(); + } + + public int getIndex() { + return this.index; + } + + public String getTime() { + return String.format("%02d",this.hour) + ":" + String.format("%02d",this.minute); + } + + public int getHour(){ + return this.hour; + } + + public int getMinute(){ + return this.minute; + } + public Calendar getAlarmCal() { + Calendar alarm = Calendar.getInstance(); + alarm.set(Calendar.HOUR_OF_DAY, this.hour); + alarm.set(Calendar.MINUTE, this.minute); + return alarm; + } + + public boolean isEnabled() { + return this.enabled; + } + + public boolean isSmartWakeup() { + return this.smartWakeup; + } + + public boolean getRepetition(int dow) { + return (this.repetition & dow) > 0; + } + + public int getRepetitionMask() { + return this.repetition; + } + + public String toPreferences() { + return String.valueOf(this.index)+','+ + String.valueOf(this.enabled)+','+ + String.valueOf(this.smartWakeup)+','+ + String.valueOf(this.repetition)+','+ + String.valueOf(this.hour)+','+ + String.valueOf(this.minute); + } + + public void setSmartWakeup(boolean smartWakeup) { + this.smartWakeup = smartWakeup; + store(); + } + + public void setRepetition(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) { + this.repetition = ALARM_ONCE | + (mon ? ALARM_MON : 0) | + (tue ? ALARM_TUE : 0) | + (wed ? ALARM_WED : 0) | + (thu ? ALARM_THU : 0) | + (fri ? ALARM_FRI : 0) | + (sat ? ALARM_SAT : 0) | + (sun ? ALARM_SUN : 0); + store(); + } + + public void setHour(int hour) { + this.hour = hour; + store(); + } + + public void setMinute(int minute) { + this.minute = minute; + store(); + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + store(); // TODO: if we have many setters, this may become a bottleneck + } + + private void store() { + //TODO: I don't like to have the alarm index both in the preference name and in the value + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext()); + String pref = PREF_MIBAND_ALARM_PREFIX +(this.index+1); + sharedPrefs.edit().putString(pref, this.toPreferences()).apply(); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java index 9a17893b8..e3a63afe0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java @@ -226,4 +226,12 @@ public class ServiceDeviceSupport implements DeviceSupport { } delegate.onScreenshotReq(); } + + @Override + public void onSetAlarms() { + if (checkBusy("set alarms")) { + return; + } + delegate.onSetAlarms(); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java new file mode 100644 index 000000000..a9c4d709a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -0,0 +1,140 @@ +package nodomain.freeyourgadget.gadgetbridge.activities; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.CheckedTextView; +import android.widget.TimePicker; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nodomain.freeyourgadget.gadgetbridge.GBAlarm; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; + +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM_PREFIX; + +public class AlarmDetails extends Activity { + + private static final Logger LOG = LoggerFactory.getLogger(AlarmDetails.class); + + + private GBAlarm alarm; + private TimePicker timePicker; + //using CheckedTextView allows for vertically aligned text + private CheckedTextView ctvSmartWakeup; + private CheckedTextView ctvMonday; + private CheckedTextView ctvTuesday; + private CheckedTextView ctvWednesday; + private CheckedTextView ctvThursday; + private CheckedTextView ctvFriday; + private CheckedTextView ctvSaturday; + private CheckedTextView ctvSunday; + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_alarm_details); + + int index = getIntent().getExtras().getInt("alarm_index"); + if (index <0 || index > 2) { + finish(); + }else { + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); + String pref = PREF_MIBAND_ALARM_PREFIX +(index+1); + alarm = new GBAlarm(sharedPrefs.getString(pref, "")); + //TODO: this is horrible and error-prone + + timePicker = (TimePicker) findViewById(R.id.alarm_time_picker); + ctvSmartWakeup = (CheckedTextView) findViewById(R.id.alarm_ctv_smart_wakeup); + ctvMonday = (CheckedTextView) findViewById(R.id.alarm_ctv_mon); + ctvTuesday = (CheckedTextView) findViewById(R.id.alarm_ctv_tue); + ctvWednesday = (CheckedTextView) findViewById(R.id.alarm_ctv_wed); + ctvThursday = (CheckedTextView) findViewById(R.id.alarm_ctv_thu); + ctvFriday = (CheckedTextView) findViewById(R.id.alarm_ctv_fri); + ctvSaturday = (CheckedTextView) findViewById(R.id.alarm_ctv_sat); + ctvSunday = (CheckedTextView) findViewById(R.id.alarm_ctv_sun); + + timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext())); + timePicker.setCurrentHour(alarm.getHour()); + timePicker.setCurrentMinute(alarm.getMinute()); + + ctvSmartWakeup.setChecked(alarm.isSmartWakeup()); + ctvSmartWakeup.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + + ctvMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON)); + ctvTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE)); + ctvWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED)); + ctvThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU)); + ctvFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI)); + ctvSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT)); + ctvSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN)); + + ctvMonday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvTuesday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvWednesday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvThursday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvFriday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvSaturday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvSunday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + + } + + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + alarm.setSmartWakeup(ctvSmartWakeup.isChecked()); + alarm.setRepetition(ctvMonday.isChecked(),ctvTuesday.isChecked(),ctvWednesday.isChecked(),ctvThursday.isChecked(),ctvFriday.isChecked(),ctvSaturday.isChecked(),ctvSunday.isChecked()); + alarm.setHour(timePicker.getCurrentHour()); + alarm.setMinute(timePicker.getCurrentMinute()); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java new file mode 100644 index 000000000..c3176d6c2 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -0,0 +1,55 @@ +package nodomain.freeyourgadget.gadgetbridge.activities; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.app.Activity; +import android.preference.PreferenceManager; +import android.widget.ListView; + + +import nodomain.freeyourgadget.gadgetbridge.BluetoothCommunicationService; +import nodomain.freeyourgadget.gadgetbridge.GBAlarm; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; + + +import java.util.ArrayList; +import java.util.List; + + +public class ConfigureAlarms extends Activity { + + ListView alarmListView; + private GBAlarmListAdapter mGBAlarmListAdapter; + + final List alarmList = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_configure_alarms); + getActionBar().setDisplayHomeAsUpEnabled(true); + + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); + //The GBAlarm class initializes the sharedPrefs values if they're missing, no need to handle it here + alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM1, GBAlarm.DEFAULT_ALARM1))); + alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM2, GBAlarm.DEFAULT_ALARM2))); + alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM3, GBAlarm.DEFAULT_ALARM3))); + + alarmListView = (ListView) findViewById(R.id.alarmListView); + mGBAlarmListAdapter = new GBAlarmListAdapter(this, alarmList); + alarmListView.setAdapter(this.mGBAlarmListAdapter); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Intent startIntent = new Intent(ConfigureAlarms.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_SET_ALARMS); + startService(startIntent); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java new file mode 100644 index 000000000..c5e6ff97a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -0,0 +1,99 @@ +package nodomain.freeyourgadget.gadgetbridge.adapter; + + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.preference.PreferenceManager; +import android.view.LayoutInflater; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.Switch; +import android.widget.TextView; + +import nodomain.freeyourgadget.gadgetbridge.GBAlarm; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.AlarmDetails; + + +import java.util.List; + +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; + + +public class GBAlarmListAdapter extends ArrayAdapter { + private final Context mContext; + + private List alarmList; + + public GBAlarmListAdapter(Context context, List alarmList) { + super(context, 0, alarmList); + + this.mContext = context; + this.alarmList = alarmList; + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + + final GBAlarm alarm = getItem(position); + + if (view == null) { + LayoutInflater inflater = (LayoutInflater) mContext + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.alarm_item, parent, false); + } + + TextView alarmTime = (TextView) view.findViewById(R.id.alarm_item_time); + Switch isEnabled = (Switch) view.findViewById(R.id.alarm_item_toggle); + TextView isSmartWakeup = (TextView) view.findViewById(R.id.alarm_smart_wakeup); + + highlightDay((TextView) view.findViewById(R.id.alarm_item_sunday), alarm.getRepetition(GBAlarm.ALARM_SUN)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_monday), alarm.getRepetition(GBAlarm.ALARM_MON)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_tuesday), alarm.getRepetition(GBAlarm.ALARM_TUE)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_wednesday), alarm.getRepetition(GBAlarm.ALARM_WED)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_thursday), alarm.getRepetition(GBAlarm.ALARM_THU)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_friday), alarm.getRepetition(GBAlarm.ALARM_FRI)); + highlightDay((TextView) view.findViewById(R.id.alarm_item_saturday), alarm.getRepetition(GBAlarm.ALARM_SAT)); + + isEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + alarm.setEnabled(isChecked); + } + }); + + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent; + startIntent = new Intent(mContext, AlarmDetails.class); + startIntent.putExtra("alarm_index", alarm.getIndex()); + mContext.startActivity(startIntent); + } + }); + alarmTime.setText(alarm.getTime()); + isEnabled.setChecked(alarm.isEnabled()); + if(alarm.isSmartWakeup()) { + isSmartWakeup.setVisibility(TextView.VISIBLE); + } else { + isSmartWakeup.setVisibility(TextView.GONE); + } + + return view; + } + + private void highlightDay(TextView view, boolean isOn) { + if (isOn) { + view.setTextColor(Color.BLUE); + } else { + view.setTextColor(Color.BLACK); + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java index 9754a5fa0..7d26e07e1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java @@ -15,6 +15,10 @@ public final class MiBandConst { public static final String PREF_USER_WEIGHT_KG = "mi_user_weight_kg"; public static final String PREF_MIBAND_WEARSIDE = "mi_wearside"; public static final String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_ + public static final String PREF_MIBAND_ALARM_PREFIX = "mi_alarm"; + public static final String PREF_MIBAND_ALARM1 = PREF_MIBAND_ALARM_PREFIX +"1"; + public static final String PREF_MIBAND_ALARM2 = PREF_MIBAND_ALARM_PREFIX +"2"; + public static final String PREF_MIBAND_ALARM3 = PREF_MIBAND_ALARM_PREFIX +"3"; public static final String ORIGIN_SMS = "sms"; public static final String ORIGIN_INCOMING_CALL = "incoming_call"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java index ff53ae32a..e9500f365 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandService.java @@ -134,6 +134,9 @@ public class MiBandService { public static final byte COMMAND_CONFIRM_ACTIVITY_DATA_TRANSFER_COMPLETE = 0xa; public static final byte COMMAND_FETCH_DATA = 0x6; + + public static final byte COMMAND_SET_TIMER = 0x4; + /* @@ -152,8 +155,6 @@ public class MiBandService { public static final COMMAND_SET_REALTIME_STEPS_NOTIFICATION = 0x3t - public static final COMMAND_SET_TIMER = 0x4t - public static final COMMAND_SET_WEAR_LOCATION = 0xft public static final COMMAND_STOP_SYNC_DATA = 0x11t 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 40a03fb27..ef195b0b5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -18,6 +18,7 @@ import java.util.GregorianCalendar; import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; +import nodomain.freeyourgadget.gadgetbridge.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBCommand; import nodomain.freeyourgadget.gadgetbridge.GBDevice.State; @@ -44,6 +45,9 @@ import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.FLASH_ORIG import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_GENERIC; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_K9MAIL; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_SMS; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_DURATION; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PAUSE; @@ -323,6 +327,21 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { return VibrationProfile.getProfile(profileId, (byte) (repeat & 0xfff)); } + @Override + public void onSetAlarms() { + try { + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); + TransactionBuilder builder = performInitialized("Set alarm"); + queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM1, GBAlarm.DEFAULT_ALARM1)), builder, characteristic); + queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM2, GBAlarm.DEFAULT_ALARM2)), builder, characteristic); + queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM3, GBAlarm.DEFAULT_ALARM3)), builder, characteristic); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Unable to set alarms on MI device", ex); + } + } + @Override public void onSMS(String from, String body) { performPreferredNotification("sms received", ORIGIN_SMS, null); @@ -544,6 +563,25 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } } + + private void queueAlarm(GBAlarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) { + Calendar alarmCal = alarm.getAlarmCal(); + byte[] alarmMessage = new byte[] { + (byte) MiBandService.COMMAND_SET_TIMER, + (byte) alarm.getIndex(), + (byte) (alarm.isEnabled() ? 1: 0), + (byte) (alarmCal.get(Calendar.YEAR) - 2000), + (byte) alarmCal.get(Calendar.MONTH), + (byte) alarmCal.get(Calendar.DATE), + (byte) alarmCal.get(Calendar.HOUR_OF_DAY), + (byte) alarmCal.get(Calendar.MINUTE), + (byte) alarmCal.get(Calendar.SECOND), + (byte) (alarm.isSmartWakeup() ? 30 : 0), + (byte) alarm.getRepetitionMask() + }; + builder.write(characteristic, alarmMessage); + } + private void handleActivityNotif(byte[] value) { if (value.length == 11) { // byte 0 is the data type: 1 means that each minute is represented by a triplet of bytes diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java index c868adc0a..4d6fad6ea 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java @@ -38,4 +38,9 @@ public class PebbleSupport extends AbstractBTDeviceSupport { public synchronized PebbleIoThread getDeviceIOThread() { return (PebbleIoThread) super.getDeviceIOThread(); } + + @Override + public void onSetAlarms() { + //nothing to do ATM + } } diff --git a/app/src/main/res/layout/activity_alarm_details.xml b/app/src/main/res/layout/activity_alarm_details.xml new file mode 100644 index 000000000..a84c7d129 --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_details.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_configure_alarms.xml b/app/src/main/res/layout/activity_configure_alarms.xml new file mode 100644 index 000000000..83e4af074 --- /dev/null +++ b/app/src/main/res/layout/activity_configure_alarms.xml @@ -0,0 +1,16 @@ + + + + diff --git a/app/src/main/res/layout/alarm_item.xml b/app/src/main/res/layout/alarm_item.xml new file mode 100644 index 000000000..6bfa02f7d --- /dev/null +++ b/app/src/main/res/layout/alarm_item.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/controlcenter_context.xml b/app/src/main/res/menu/controlcenter_context.xml index 4002869d4..c9c07d963 100644 --- a/app/src/main/res/menu/controlcenter_context.xml +++ b/app/src/main/res/menu/controlcenter_context.xml @@ -6,6 +6,9 @@ + diff --git a/app/src/main/res/menu/menu_alarm_details.xml b/app/src/main/res/menu/menu_alarm_details.xml new file mode 100644 index 000000000..14e9fe768 --- /dev/null +++ b/app/src/main/res/menu/menu_alarm_details.xml @@ -0,0 +1,7 @@ + + + diff --git a/app/src/main/res/menu/menu_set_alarm.xml b/app/src/main/res/menu/menu_set_alarm.xml new file mode 100644 index 000000000..835ed8d52 --- /dev/null +++ b/app/src/main/res/menu/menu_set_alarm.xml @@ -0,0 +1,7 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e9bfccd75..864df02b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,5 +138,15 @@ Find lost Device Cancel to stop vibration. ChartsActivity - + Configure Alarms + Configure alarms + Alarm Details + Sun + Mon + Tue + Wed + Thu + Fri + Sat + smart wakeup From 764dd70e45b141137be31bffe0bddb817703837c Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Thu, 25 Jun 2015 12:42:47 +0200 Subject: [PATCH 2/7] low hanging fruits: - add break after case - center vertically the smart wakeup checkbox --- .../BluetoothCommunicationService.java | 2 +- .../res/layout/activity_alarm_details.xml | 44 +++++++++++-------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java index 74562d351..bd49a1f4d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java @@ -268,7 +268,7 @@ public class BluetoothCommunicationService extends Service { break; case ACTION_SET_ALARMS: mDeviceSupport.onSetAlarms(); - + break; } return START_STICKY; diff --git a/app/src/main/res/layout/activity_alarm_details.xml b/app/src/main/res/layout/activity_alarm_details.xml index a84c7d129..093755186 100644 --- a/app/src/main/res/layout/activity_alarm_details.xml +++ b/app/src/main/res/layout/activity_alarm_details.xml @@ -1,5 +1,6 @@ - - + - + + + + - - + From dc3ed1659c109face110b07d55725a9550ad05bc Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Thu, 25 Jun 2015 14:34:21 +0200 Subject: [PATCH 3/7] use parcelable for passing alarms around --- .../BluetoothCommunicationService.java | 4 +- .../gadgetbridge/EventHandler.java | 3 +- .../freeyourgadget/gadgetbridge/GBAlarm.java | 51 +++++- .../gadgetbridge/ServiceDeviceSupport.java | 5 +- .../gadgetbridge/activities/AlarmDetails.java | 149 +++++++++--------- .../activities/ConfigureAlarms.java | 4 +- .../adapter/GBAlarmListAdapter.java | 2 +- .../gadgetbridge/miband/MiBandSupport.java | 10 +- .../gadgetbridge/pebble/PebbleSupport.java | 5 +- 9 files changed, 142 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java index bd49a1f4d..83a4ae505 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java @@ -21,6 +21,7 @@ import android.widget.Toast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBDevice.State; @@ -267,7 +268,8 @@ public class BluetoothCommunicationService extends Service { mStarted = true; break; case ACTION_SET_ALARMS: - mDeviceSupport.onSetAlarms(); + ArrayList alarms = intent.getParcelableArrayListExtra("alarms"); + mDeviceSupport.onSetAlarms(alarms); break; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java index 29d7b1cce..78995fd37 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java @@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge; import android.net.Uri; +import java.util.ArrayList; import java.util.UUID; public interface EventHandler { @@ -13,7 +14,7 @@ public interface EventHandler { void onSetTime(long ts); - void onSetAlarms(); + void onSetAlarms(ArrayList alarms); void onSetCallState(String number, String name, GBCommand command); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java index 8232423e6..83dc8cae3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java @@ -1,13 +1,16 @@ package nodomain.freeyourgadget.gadgetbridge; import android.content.SharedPreferences; +import android.os.Parcel; +import android.os.Parcelable; import android.preference.PreferenceManager; import java.util.Calendar; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM_PREFIX; -public class GBAlarm { +public class GBAlarm implements Parcelable { + private int index; private boolean enabled; private boolean smartWakeup; @@ -50,6 +53,41 @@ public class GBAlarm { store(); } + private static GBAlarm readFromParcel(Parcel pc) { + int index = pc.readInt(); + boolean enabled = Boolean.parseBoolean(pc.readString()); + boolean smartWakeup = Boolean.parseBoolean(pc.readString()); + int repetition = pc.readInt(); + int hour = pc.readInt(); + int minute = pc.readInt(); + return new GBAlarm(index, enabled, smartWakeup, (byte)repetition, hour, minute); + } + + @Override + public boolean equals(Object o) { + if (o instanceof GBAlarm) { + GBAlarm comp = (GBAlarm)o; + return comp.getIndex() == getIndex(); + } else { + return false; + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(this.index); + dest.writeString(String.valueOf(this.enabled)); + dest.writeString(String.valueOf(this.smartWakeup)); + dest.writeInt(this.repetition); + dest.writeInt(this.hour); + dest.writeInt(this.minute); + } + public int getIndex() { return this.index; } @@ -135,4 +173,15 @@ public class GBAlarm { String pref = PREF_MIBAND_ALARM_PREFIX +(this.index+1); sharedPrefs.edit().putString(pref, this.toPreferences()).apply(); } + + public static final Creator CREATOR = new Creator() { + public GBAlarm createFromParcel(Parcel in) { + return readFromParcel(in); + } + + public GBAlarm[] newArray(int size) { + return new GBAlarm[size]; + } + + }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java index e3a63afe0..8ea3df39d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java @@ -7,6 +7,7 @@ import android.net.Uri; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.UUID; /** @@ -228,10 +229,10 @@ public class ServiceDeviceSupport implements DeviceSupport { } @Override - public void onSetAlarms() { + public void onSetAlarms(ArrayList alarms) { if (checkBusy("set alarms")) { return; } - delegate.onSetAlarms(); + delegate.onSetAlarms(alarms); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java index a9c4d709a..41cdc893a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Parcelable; import android.preference.PreferenceManager; import android.text.format.DateFormat; import android.view.View; @@ -42,89 +43,81 @@ public class AlarmDetails extends Activity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_alarm_details); - int index = getIntent().getExtras().getInt("alarm_index"); - if (index <0 || index > 2) { - finish(); - }else { - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); - String pref = PREF_MIBAND_ALARM_PREFIX +(index+1); - alarm = new GBAlarm(sharedPrefs.getString(pref, "")); - //TODO: this is horrible and error-prone + Parcelable p = getIntent().getExtras().getParcelable("alarm"); + alarm = (GBAlarm) p; - timePicker = (TimePicker) findViewById(R.id.alarm_time_picker); - ctvSmartWakeup = (CheckedTextView) findViewById(R.id.alarm_ctv_smart_wakeup); - ctvMonday = (CheckedTextView) findViewById(R.id.alarm_ctv_mon); - ctvTuesday = (CheckedTextView) findViewById(R.id.alarm_ctv_tue); - ctvWednesday = (CheckedTextView) findViewById(R.id.alarm_ctv_wed); - ctvThursday = (CheckedTextView) findViewById(R.id.alarm_ctv_thu); - ctvFriday = (CheckedTextView) findViewById(R.id.alarm_ctv_fri); - ctvSaturday = (CheckedTextView) findViewById(R.id.alarm_ctv_sat); - ctvSunday = (CheckedTextView) findViewById(R.id.alarm_ctv_sun); + timePicker = (TimePicker) findViewById(R.id.alarm_time_picker); + ctvSmartWakeup = (CheckedTextView) findViewById(R.id.alarm_ctv_smart_wakeup); + ctvMonday = (CheckedTextView) findViewById(R.id.alarm_ctv_mon); + ctvTuesday = (CheckedTextView) findViewById(R.id.alarm_ctv_tue); + ctvWednesday = (CheckedTextView) findViewById(R.id.alarm_ctv_wed); + ctvThursday = (CheckedTextView) findViewById(R.id.alarm_ctv_thu); + ctvFriday = (CheckedTextView) findViewById(R.id.alarm_ctv_fri); + ctvSaturday = (CheckedTextView) findViewById(R.id.alarm_ctv_sat); + ctvSunday = (CheckedTextView) findViewById(R.id.alarm_ctv_sun); - timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext())); - timePicker.setCurrentHour(alarm.getHour()); - timePicker.setCurrentMinute(alarm.getMinute()); + timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext())); + timePicker.setCurrentHour(alarm.getHour()); + timePicker.setCurrentMinute(alarm.getMinute()); - ctvSmartWakeup.setChecked(alarm.isSmartWakeup()); - ctvSmartWakeup.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); + ctvSmartWakeup.setChecked(alarm.isSmartWakeup()); + ctvSmartWakeup.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); - ctvMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON)); - ctvTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE)); - ctvWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED)); - ctvThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU)); - ctvFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI)); - ctvSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT)); - ctvSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN)); + ctvMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON)); + ctvTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE)); + ctvWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED)); + ctvThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU)); + ctvFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI)); + ctvSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT)); + ctvSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN)); - ctvMonday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvTuesday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvWednesday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvThursday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvFriday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvSaturday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvSunday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - - } + ctvMonday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvTuesday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvWednesday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvThursday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvFriday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvSaturday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); + ctvSunday.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((CheckedTextView) v).toggle(); + } + }); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java index c3176d6c2..b5a344565 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -26,7 +26,7 @@ public class ConfigureAlarms extends Activity { ListView alarmListView; private GBAlarmListAdapter mGBAlarmListAdapter; - final List alarmList = new ArrayList<>(); + final ArrayList alarmList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -49,7 +49,9 @@ public class ConfigureAlarms extends Activity { protected void onDestroy() { super.onDestroy(); Intent startIntent = new Intent(ConfigureAlarms.this, BluetoothCommunicationService.class); + startIntent.putParcelableArrayListExtra("alarms", alarmList); startIntent.setAction(BluetoothCommunicationService.ACTION_SET_ALARMS); startService(startIntent); } + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java index c5e6ff97a..78e6c3be1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -74,7 +74,7 @@ public class GBAlarmListAdapter extends ArrayAdapter { public void onClick(View v) { Intent startIntent; startIntent = new Intent(mContext, AlarmDetails.class); - startIntent.putExtra("alarm_index", alarm.getIndex()); + startIntent.putExtra("alarm", alarm); mContext.startActivity(startIntent); } }); 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 ef195b0b5..678d9188c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.text.DateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; @@ -328,14 +329,13 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { } @Override - public void onSetAlarms() { + public void onSetAlarms(ArrayList alarms) { try { - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext()); BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); TransactionBuilder builder = performInitialized("Set alarm"); - queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM1, GBAlarm.DEFAULT_ALARM1)), builder, characteristic); - queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM2, GBAlarm.DEFAULT_ALARM2)), builder, characteristic); - queueAlarm(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM3, GBAlarm.DEFAULT_ALARM3)), builder, characteristic); + for (GBAlarm alarm : alarms) { + queueAlarm(alarm, builder, characteristic); + } builder.queue(getQueue()); } catch (IOException ex) { LOG.error("Unable to set alarms on MI device", ex); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java index 4d6fad6ea..43b50d967 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleSupport.java @@ -2,7 +2,10 @@ package nodomain.freeyourgadget.gadgetbridge.pebble; import android.net.Uri; +import java.util.ArrayList; + import nodomain.freeyourgadget.gadgetbridge.AbstractBTDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.GBDeviceIoThread; import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceProtocol; @@ -40,7 +43,7 @@ public class PebbleSupport extends AbstractBTDeviceSupport { } @Override - public void onSetAlarms() { + public void onSetAlarms(ArrayList alarms) { //nothing to do ATM } } From 109b2bef4da7b457d2c7a6810d6eb9b03d4a85a2 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Thu, 25 Jun 2015 14:48:46 +0200 Subject: [PATCH 4/7] add a Toast to confirm the transfer of the alarm or to warn if the transfer wasn't possible. --- .../freeyourgadget/gadgetbridge/miband/MiBandSupport.java | 6 +++--- app/src/main/res/values/strings.xml | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) 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 678d9188c..50356f3cf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -6,6 +6,7 @@ import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.preference.PreferenceManager; +import android.widget.Toast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,9 +47,6 @@ import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.FLASH_ORIG import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_GENERIC; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_K9MAIL; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.ORIGIN_SMS; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_COUNT; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_DURATION; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.VIBRATION_PAUSE; @@ -337,7 +335,9 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { queueAlarm(alarm, builder, characteristic); } builder.queue(getQueue()); + Toast.makeText(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_ok), Toast.LENGTH_SHORT).show(); } catch (IOException ex) { + Toast.makeText(getContext(), getContext().getString(R.string.user_feedback_miband_set_alarms_failed), Toast.LENGTH_LONG).show(); LOG.error("Unable to set alarms on MI device", ex); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 864df02b6..b1685f25f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -149,4 +149,6 @@ Fri Sat smart wakeup + There was an error setting the alarms, please try again! + Alarms sent to device! From 900511760c4152a9f1aabd56e553415b788dd9ce Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Fri, 26 Jun 2015 17:22:42 +0200 Subject: [PATCH 5/7] further improvements: - the day of week are evenly spread across the screen in the alarms detail activity - the alarms are stored in a single shared preference (as a set) NB: you'll have to reset your alarms if you used a previous version (and also manually clean the shared preferences, but this is not needed) - the list of alarms gets correctly updated after editing a specific alarm - the actionbar back button saves the alarm status, the device back button doesn't. I'm not sure if it's a bug or a feature :) --- .../freeyourgadget/gadgetbridge/GBAlarm.java | 55 +++++++--- .../gadgetbridge/activities/AlarmDetails.java | 29 ++--- .../activities/ConfigureAlarms.java | 77 ++++++++----- .../adapter/GBAlarmListAdapter.java | 102 ++++++++++++++---- .../gadgetbridge/miband/MiBandConst.java | 5 +- .../res/layout/activity_alarm_details.xml | 53 +++++---- .../res/layout/activity_configure_alarms.xml | 2 +- 7 files changed, 226 insertions(+), 97 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java index 83dc8cae3..e53b71f23 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java @@ -6,10 +6,14 @@ import android.os.Parcelable; import android.preference.PreferenceManager; import java.util.Calendar; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM_PREFIX; +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARMS; -public class GBAlarm implements Parcelable { + +public class GBAlarm implements Parcelable, Comparable { private int index; private boolean enabled; @@ -27,9 +31,8 @@ public class GBAlarm implements Parcelable { public static final byte ALARM_SAT = 32; public static final byte ALARM_SUN = 64; - public static final String DEFAULT_ALARM1 = "0,false,true,31,7,30"; - public static final String DEFAULT_ALARM2 = "1,false,false,96,8,00"; - public static final String DEFAULT_ALARM3 = "2,false,false,0,15,30"; + public static final String[] DEFAULT_ALARMS = {"2,false,false,0,15,30","1,false,false,96,8,0","0,false,true,31,7,30"}; + public GBAlarm(int index, boolean enabled, boolean smartWakeup, byte repetition, int hour, int minute) { this.index = index; @@ -38,7 +41,6 @@ public class GBAlarm implements Parcelable { this.repetition = repetition; this.hour = hour; this.minute = minute; - store(); } public GBAlarm(String fromPreferences){ @@ -50,7 +52,6 @@ public class GBAlarm implements Parcelable { this.repetition = Integer.parseInt(tokens[3]); this.hour = Integer.parseInt(tokens[4]); this.minute = Integer.parseInt(tokens[5]); - store(); } private static GBAlarm readFromParcel(Parcel pc) { @@ -73,6 +74,11 @@ public class GBAlarm implements Parcelable { } } + @Override + public int hashCode() { + return getIndex(); + } + @Override public int describeContents() { return 0; @@ -88,6 +94,16 @@ public class GBAlarm implements Parcelable { dest.writeInt(this.minute); } + @Override + public int compareTo(Object another) { + if (this.getIndex() < ((GBAlarm)another).getIndex()) { + return -1; + }else if (this.getIndex() > ((GBAlarm)another).getIndex()) { + return 1; + } + return 0; + } + public int getIndex() { return this.index; } @@ -137,7 +153,6 @@ public class GBAlarm implements Parcelable { public void setSmartWakeup(boolean smartWakeup) { this.smartWakeup = smartWakeup; - store(); } public void setRepetition(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) { @@ -149,29 +164,37 @@ public class GBAlarm implements Parcelable { (fri ? ALARM_FRI : 0) | (sat ? ALARM_SAT : 0) | (sun ? ALARM_SUN : 0); - store(); } public void setHour(int hour) { this.hour = hour; - store(); } public void setMinute(int minute) { this.minute = minute; - store(); } public void setEnabled(boolean enabled) { this.enabled = enabled; - store(); // TODO: if we have many setters, this may become a bottleneck } - private void store() { - //TODO: I don't like to have the alarm index both in the preference name and in the value + public void store() { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext()); - String pref = PREF_MIBAND_ALARM_PREFIX +(this.index+1); - sharedPrefs.edit().putString(pref, this.toPreferences()).apply(); + Set preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet()); + //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 newPrefs = new HashSet(preferencesAlarmListSet); + + Iterator iterator = newPrefs.iterator(); + + while (iterator.hasNext()) { + String alarmString = iterator.next(); + if(this.equals(new GBAlarm(alarmString))) { + iterator.remove(); + } + } + newPrefs.add(this.toPreferences()); + sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, newPrefs).commit(); + return; } public static final Creator CREATOR = new Creator() { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java index 41cdc893a..1f689de55 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -1,29 +1,20 @@ package nodomain.freeyourgadget.gadgetbridge.activities; import android.app.Activity; -import android.content.SharedPreferences; import android.os.Bundle; import android.os.Parcelable; -import android.preference.PreferenceManager; import android.text.format.DateFormat; +import android.view.MenuItem; import android.view.View; import android.widget.CheckedTextView; import android.widget.TimePicker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import nodomain.freeyourgadget.gadgetbridge.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM_PREFIX; - public class AlarmDetails extends Activity { - private static final Logger LOG = LoggerFactory.getLogger(AlarmDetails.class); - - private GBAlarm alarm; private TimePicker timePicker; //using CheckedTextView allows for vertically aligned text @@ -121,13 +112,23 @@ public class AlarmDetails extends Activity { } - @Override - protected void onDestroy() { - super.onDestroy(); + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // back button + updateAlarm(); + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void updateAlarm() { alarm.setSmartWakeup(ctvSmartWakeup.isChecked()); - alarm.setRepetition(ctvMonday.isChecked(),ctvTuesday.isChecked(),ctvWednesday.isChecked(),ctvThursday.isChecked(),ctvFriday.isChecked(),ctvSaturday.isChecked(),ctvSunday.isChecked()); + alarm.setRepetition(ctvMonday.isChecked(), ctvTuesday.isChecked(), ctvWednesday.isChecked(), ctvThursday.isChecked(), ctvFriday.isChecked(), ctvSaturday.isChecked(), ctvSunday.isChecked()); alarm.setHour(timePicker.getCurrentHour()); alarm.setMinute(timePicker.getCurrentMinute()); + alarm.store(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java index b5a344565..ce3c147bc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ConfigureAlarms.java @@ -1,57 +1,86 @@ package nodomain.freeyourgadget.gadgetbridge.activities; +import android.app.ListActivity; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import android.app.Activity; import android.preference.PreferenceManager; -import android.widget.ListView; +import android.view.MenuItem; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import nodomain.freeyourgadget.gadgetbridge.BluetoothCommunicationService; import nodomain.freeyourgadget.gadgetbridge.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; + +import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARMS; -import java.util.ArrayList; -import java.util.List; +public class ConfigureAlarms extends ListActivity { - -public class ConfigureAlarms extends Activity { - - ListView alarmListView; private GBAlarmListAdapter mGBAlarmListAdapter; - - final ArrayList alarmList = new ArrayList<>(); + private Set preferencesAlarmListSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_configure_alarms); getActionBar().setDisplayHomeAsUpEnabled(true); SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); - //The GBAlarm class initializes the sharedPrefs values if they're missing, no need to handle it here - alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM1, GBAlarm.DEFAULT_ALARM1))); - alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM2, GBAlarm.DEFAULT_ALARM2))); - alarmList.add(new GBAlarm(sharedPrefs.getString(PREF_MIBAND_ALARM3, GBAlarm.DEFAULT_ALARM3))); + preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet()); + if (preferencesAlarmListSet.isEmpty()) { + //initialize the preferences + preferencesAlarmListSet = new HashSet<>(Arrays.asList(GBAlarm.DEFAULT_ALARMS)); + sharedPrefs.edit().putStringSet(PREF_MIBAND_ALARMS, preferencesAlarmListSet).commit(); + } + + mGBAlarmListAdapter = new GBAlarmListAdapter(this, preferencesAlarmListSet); + + setListAdapter(mGBAlarmListAdapter); - alarmListView = (ListView) findViewById(R.id.alarmListView); - mGBAlarmListAdapter = new GBAlarmListAdapter(this, alarmList); - alarmListView.setAdapter(this.mGBAlarmListAdapter); } @Override - protected void onDestroy() { - super.onDestroy(); + protected void onResume() { + super.onResume(); + + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); + preferencesAlarmListSet = sharedPrefs.getStringSet(PREF_MIBAND_ALARMS, new HashSet()); + + mGBAlarmListAdapter.setAlarmList(preferencesAlarmListSet); + mGBAlarmListAdapter.notifyDataSetChanged(); + + sendAlarmsToDevice(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // back button + sendAlarmsToDevice(); + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + public void configureAlarm(GBAlarm alarm) { + Intent startIntent; + startIntent = new Intent(getApplicationContext(), AlarmDetails.class); + startIntent.putExtra("alarm", alarm); + startActivity(startIntent); + } + + private void sendAlarmsToDevice() { Intent startIntent = new Intent(ConfigureAlarms.this, BluetoothCommunicationService.class); - startIntent.putParcelableArrayListExtra("alarms", alarmList); + startIntent.putParcelableArrayListExtra("alarms", mGBAlarmListAdapter.getAlarmList()); startIntent.setAction(BluetoothCommunicationService.ACTION_SET_ALARMS); startService(startIntent); } - } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java index 78e6c3be1..3952647f1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -1,13 +1,9 @@ package nodomain.freeyourgadget.gadgetbridge.adapter; -import android.app.Activity; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Color; -import android.preference.PreferenceManager; import android.view.LayoutInflater; -import android.content.Intent; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -15,30 +11,100 @@ import android.widget.CompoundButton; import android.widget.Switch; import android.widget.TextView; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + import nodomain.freeyourgadget.gadgetbridge.GBAlarm; import nodomain.freeyourgadget.gadgetbridge.R; -import nodomain.freeyourgadget.gadgetbridge.activities.AlarmDetails; - - -import java.util.List; - -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM1; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM2; -import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.PREF_MIBAND_ALARM3; +import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms; public class GBAlarmListAdapter extends ArrayAdapter { + + private final Context mContext; + private ArrayList alarmList; - private List alarmList; - - public GBAlarmListAdapter(Context context, List alarmList) { + public GBAlarmListAdapter(Context context, ArrayList alarmList) { super(context, 0, alarmList); this.mContext = context; this.alarmList = alarmList; } + public GBAlarmListAdapter(Context context,Set preferencesAlarmListSet) { + super(context, 0, new ArrayList()); + + this.mContext = context; + alarmList = new ArrayList(); + + if (preferencesAlarmListSet != null) { + Iterator iterator = preferencesAlarmListSet.iterator(); + + while (iterator.hasNext()) { + String alarmString = iterator.next(); + alarmList.add(new GBAlarm(alarmString)); + } + } + + Collections.sort(alarmList); + } + + public void setAlarmList(Set preferencesAlarmListSet) { + alarmList = new ArrayList(); + + if (preferencesAlarmListSet != null) { + Iterator iterator = preferencesAlarmListSet.iterator(); + + while (iterator.hasNext()) { + String alarmString = iterator.next(); + alarmList.add(new GBAlarm(alarmString)); + } + } + + Collections.sort(alarmList); + } + + public ArrayList getAlarmList() { + return alarmList; + } + + + public void update(GBAlarm alarm) { + for (GBAlarm a : alarmList) { + if(alarm.equals(a)) { + a = alarm; + } + } + alarm.store(); + } + + @Override + public int getCount() { + if (alarmList != null) { + return alarmList.size(); + } + return 0; + } + + @Override + public GBAlarm getItem(int position) { + if (alarmList != null) { + return alarmList.get(position); + } + return null; + } + + @Override + public long getItemId(int position) { + if (alarmList != null) { + return alarmList.get(position).getIndex(); + } + return 0; + } + @Override public View getView(int position, View view, ViewGroup parent) { @@ -66,16 +132,14 @@ public class GBAlarmListAdapter extends ArrayAdapter { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { alarm.setEnabled(isChecked); + update(alarm); } }); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent startIntent; - startIntent = new Intent(mContext, AlarmDetails.class); - startIntent.putExtra("alarm", alarm); - mContext.startActivity(startIntent); + ((ConfigureAlarms)mContext).configureAlarm(alarm); } }); alarmTime.setText(alarm.getTime()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java index 7d26e07e1..d85cd5ebd 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandConst.java @@ -15,10 +15,7 @@ public final class MiBandConst { public static final String PREF_USER_WEIGHT_KG = "mi_user_weight_kg"; public static final String PREF_MIBAND_WEARSIDE = "mi_wearside"; public static final String PREF_MIBAND_ADDRESS = "development_miaddr"; // FIXME: should be prefixed mi_ - public static final String PREF_MIBAND_ALARM_PREFIX = "mi_alarm"; - public static final String PREF_MIBAND_ALARM1 = PREF_MIBAND_ALARM_PREFIX +"1"; - public static final String PREF_MIBAND_ALARM2 = PREF_MIBAND_ALARM_PREFIX +"2"; - public static final String PREF_MIBAND_ALARM3 = PREF_MIBAND_ALARM_PREFIX +"3"; + public static final String PREF_MIBAND_ALARMS = "mi_alarms"; public static final String ORIGIN_SMS = "sms"; public static final String ORIGIN_INCOMING_CALL = "incoming_call"; diff --git a/app/src/main/res/layout/activity_alarm_details.xml b/app/src/main/res/layout/activity_alarm_details.xml index 093755186..fbcc82a88 100644 --- a/app/src/main/res/layout/activity_alarm_details.xml +++ b/app/src/main/res/layout/activity_alarm_details.xml @@ -18,7 +18,9 @@ android:layout_height="wrap_content" android:id="@+id/alarm_time_picker" android:layout_alignParentTop="true" - android:layout_alignParentStart="true" /> + android:layout_alignParentStart="true" + android:timePickerMode="clock" + android:layout_weight="1" /> + android:layout_gravity="center_vertical" + android:gravity="center_horizontal" + android:layout_weight="1" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> + android:drawableTop="@drawable/abc_btn_check_material" + android:layout_weight="1" + android:enabled="true" + android:gravity="center_horizontal" /> diff --git a/app/src/main/res/layout/activity_configure_alarms.xml b/app/src/main/res/layout/activity_configure_alarms.xml index 83e4af074..3dd725a24 100644 --- a/app/src/main/res/layout/activity_configure_alarms.xml +++ b/app/src/main/res/layout/activity_configure_alarms.xml @@ -10,7 +10,7 @@ android:descendantFocusability="blocksDescendants" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:id="@+id/alarmListView" + android:id="@android:id/list" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> From 371a7bb4afc3ea31062f05d8f99080f20b362fa6 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sat, 27 Jun 2015 18:32:13 +0200 Subject: [PATCH 6/7] Get rid of the Checkedtextview because they weren't in line with the our style --- .../gadgetbridge/activities/AlarmDetails.java | 107 ++----- .../res/layout/activity_alarm_details.xml | 303 ++++++++++++------ 2 files changed, 232 insertions(+), 178 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java index 1f689de55..db8a45bb7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AlarmDetails.java @@ -5,8 +5,7 @@ import android.os.Bundle; import android.os.Parcelable; import android.text.format.DateFormat; import android.view.MenuItem; -import android.view.View; -import android.widget.CheckedTextView; +import android.widget.CheckBox; import android.widget.TimePicker; import nodomain.freeyourgadget.gadgetbridge.GBAlarm; @@ -17,17 +16,14 @@ public class AlarmDetails extends Activity { private GBAlarm alarm; private TimePicker timePicker; - //using CheckedTextView allows for vertically aligned text - private CheckedTextView ctvSmartWakeup; - private CheckedTextView ctvMonday; - private CheckedTextView ctvTuesday; - private CheckedTextView ctvWednesday; - private CheckedTextView ctvThursday; - private CheckedTextView ctvFriday; - private CheckedTextView ctvSaturday; - private CheckedTextView ctvSunday; - - + private CheckBox cbSmartWakeup; + private CheckBox cbMonday; + private CheckBox cbTuesday; + private CheckBox cbWednesday; + private CheckBox cbThursday; + private CheckBox cbFriday; + private CheckBox cbSaturday; + private CheckBox cbSunday; @Override protected void onCreate(Bundle savedInstanceState) { @@ -38,77 +34,28 @@ public class AlarmDetails extends Activity { alarm = (GBAlarm) p; timePicker = (TimePicker) findViewById(R.id.alarm_time_picker); - ctvSmartWakeup = (CheckedTextView) findViewById(R.id.alarm_ctv_smart_wakeup); - ctvMonday = (CheckedTextView) findViewById(R.id.alarm_ctv_mon); - ctvTuesday = (CheckedTextView) findViewById(R.id.alarm_ctv_tue); - ctvWednesday = (CheckedTextView) findViewById(R.id.alarm_ctv_wed); - ctvThursday = (CheckedTextView) findViewById(R.id.alarm_ctv_thu); - ctvFriday = (CheckedTextView) findViewById(R.id.alarm_ctv_fri); - ctvSaturday = (CheckedTextView) findViewById(R.id.alarm_ctv_sat); - ctvSunday = (CheckedTextView) findViewById(R.id.alarm_ctv_sun); + cbSmartWakeup = (CheckBox) findViewById(R.id.alarm_cb_smart_wakeup); + cbMonday = (CheckBox) findViewById(R.id.alarm_cb_mon); + cbTuesday = (CheckBox) findViewById(R.id.alarm_cb_tue); + cbWednesday = (CheckBox) findViewById(R.id.alarm_cb_wed); + cbThursday = (CheckBox) findViewById(R.id.alarm_cb_thu); + cbFriday = (CheckBox) findViewById(R.id.alarm_cb_fri); + cbSaturday = (CheckBox) findViewById(R.id.alarm_cb_sat); + cbSunday = (CheckBox) findViewById(R.id.alarm_cb_sun); timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext())); timePicker.setCurrentHour(alarm.getHour()); timePicker.setCurrentMinute(alarm.getMinute()); - ctvSmartWakeup.setChecked(alarm.isSmartWakeup()); - ctvSmartWakeup.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); + cbSmartWakeup.setChecked(alarm.isSmartWakeup()); - ctvMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON)); - ctvTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE)); - ctvWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED)); - ctvThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU)); - ctvFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI)); - ctvSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT)); - ctvSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN)); - - ctvMonday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvTuesday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvWednesday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvThursday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvFriday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvSaturday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); - ctvSunday.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((CheckedTextView) v).toggle(); - } - }); + cbMonday.setChecked(alarm.getRepetition(GBAlarm.ALARM_MON)); + cbTuesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_TUE)); + cbWednesday.setChecked(alarm.getRepetition(GBAlarm.ALARM_WED)); + cbThursday.setChecked(alarm.getRepetition(GBAlarm.ALARM_THU)); + cbFriday.setChecked(alarm.getRepetition(GBAlarm.ALARM_FRI)); + cbSaturday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SAT)); + cbSunday.setChecked(alarm.getRepetition(GBAlarm.ALARM_SUN)); } @@ -125,8 +72,8 @@ public class AlarmDetails extends Activity { } private void updateAlarm() { - alarm.setSmartWakeup(ctvSmartWakeup.isChecked()); - alarm.setRepetition(ctvMonday.isChecked(), ctvTuesday.isChecked(), ctvWednesday.isChecked(), ctvThursday.isChecked(), ctvFriday.isChecked(), ctvSaturday.isChecked(), ctvSunday.isChecked()); + alarm.setSmartWakeup(cbSmartWakeup.isChecked()); + alarm.setRepetition(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked()); alarm.setHour(timePicker.getCurrentHour()); alarm.setMinute(timePicker.getCurrentMinute()); alarm.store(); diff --git a/app/src/main/res/layout/activity_alarm_details.xml b/app/src/main/res/layout/activity_alarm_details.xml index fbcc82a88..3a4d36d05 100644 --- a/app/src/main/res/layout/activity_alarm_details.xml +++ b/app/src/main/res/layout/activity_alarm_details.xml @@ -22,17 +22,31 @@ android:timePickerMode="clock" android:layout_weight="1" /> - + android:layout_width="wrap_content" + android:layout_height="match_parent"> + + + + + + - + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="1"> - + - + - + - + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="1"> - + - + + + + + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="1"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3068d687bf19a0b3ec7afd792edae344f5fad914 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sat, 27 Jun 2015 18:56:05 +0200 Subject: [PATCH 7/7] Adressed some of the observations made re the last commits. --- .../freeyourgadget/gadgetbridge/GBAlarm.java | 1 + .../adapter/GBAlarmListAdapter.java | 18 ++++-------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java index e53b71f23..7c542a4d6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBAlarm.java @@ -190,6 +190,7 @@ public class GBAlarm implements Parcelable, Comparable { String alarmString = iterator.next(); if(this.equals(new GBAlarm(alarmString))) { iterator.remove(); + break; } } newPrefs.add(this.toPreferences()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java index 3952647f1..3abf16221 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBAlarmListAdapter.java @@ -40,13 +40,8 @@ public class GBAlarmListAdapter extends ArrayAdapter { this.mContext = context; alarmList = new ArrayList(); - if (preferencesAlarmListSet != null) { - Iterator iterator = preferencesAlarmListSet.iterator(); - - while (iterator.hasNext()) { - String alarmString = iterator.next(); - alarmList.add(new GBAlarm(alarmString)); - } + for (String alarmString : preferencesAlarmListSet) { + alarmList.add(new GBAlarm(alarmString)); } Collections.sort(alarmList); @@ -55,13 +50,8 @@ public class GBAlarmListAdapter extends ArrayAdapter { public void setAlarmList(Set preferencesAlarmListSet) { alarmList = new ArrayList(); - if (preferencesAlarmListSet != null) { - Iterator iterator = preferencesAlarmListSet.iterator(); - - while (iterator.hasNext()) { - String alarmString = iterator.next(); - alarmList.add(new GBAlarm(alarmString)); - } + for (String alarmString : preferencesAlarmListSet) { + alarmList.add(new GBAlarm(alarmString)); } Collections.sort(alarmList);