1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-30 14:02:56 +01:00

Improved DB-based alarms

- got rid of GBAlarm
- added migration for prefs-based alarms
- various cleanups
This commit is contained in:
cpfeiffer 2019-01-07 01:10:57 +01:00
parent e7dc55821d
commit 903b50c2c5
18 changed files with 333 additions and 356 deletions

View File

@ -345,6 +345,7 @@ public class GBDaoGenerator {
private static void addAlarms(Schema schema, Entity user, Entity device) {
Entity alarm = addEntity(schema, "Alarm");
alarm.implementsInterface("nodomain.freeyourgadget.gadgetbridge.model.Alarm");
Property deviceId = alarm.addLongProperty("deviceId").notNull().getProperty();
Property userId = alarm.addLongProperty("userId").notNull().getProperty();
Property position = alarm.addIntProperty("position").notNull().getProperty();
@ -355,8 +356,11 @@ public class GBDaoGenerator {
indexUnique.makeUnique();
alarm.addIndex(indexUnique);
alarm.addBooleanProperty("enabled").notNull();
alarm.addBooleanProperty("smartAlarm").notNull();
alarm.addIntProperty("repetition").notNull();
alarm.addBooleanProperty("smartWakeup").notNull();
alarm.addIntProperty("repetition").notNull().codeBeforeGetter(
"public boolean isRepetitive() { return getRepetition() != ALARM_ONCE; } " +
"public boolean getRepetition(int dow) { return (this.repetition & dow) > 0; }"
);
alarm.addIntProperty("hour").notNull();
alarm.addIntProperty("minute").notNull();
alarm.addToOne(user, userId);

View File

@ -31,7 +31,6 @@ import java.util.Calendar;
import java.util.GregorianCalendar;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.util.GB;

View File

@ -26,14 +26,16 @@ import android.widget.TimePicker;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
public class AlarmDetails extends AbstractGBActivity {
private GBAlarm alarm;
private Alarm alarm;
private TimePicker timePicker;
private CheckedTextView cbSmartWakeup;
private CheckedTextView cbMonday;
@ -50,7 +52,7 @@ public class AlarmDetails extends AbstractGBActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_details);
alarm = getIntent().getParcelableExtra("alarm");
alarm = (Alarm) getIntent().getSerializableExtra(nodomain.freeyourgadget.gadgetbridge.model.Alarm.EXTRA_ALARM);
device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
timePicker = findViewById(R.id.alarm_time_picker);
@ -109,17 +111,17 @@ public class AlarmDetails extends AbstractGBActivity {
timePicker.setCurrentHour(alarm.getHour());
timePicker.setCurrentMinute(alarm.getMinute());
cbSmartWakeup.setChecked(alarm.isSmartWakeup());
cbSmartWakeup.setChecked(alarm.getSmartWakeup());
int smartAlarmVisibility = supportsSmartWakeup() ? View.VISIBLE : View.GONE;
cbSmartWakeup.setVisibility(smartAlarmVisibility);
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));
cbMonday.setChecked(alarm.getRepetition(Alarm.ALARM_MON));
cbTuesday.setChecked(alarm.getRepetition(Alarm.ALARM_TUE));
cbWednesday.setChecked(alarm.getRepetition(Alarm.ALARM_WED));
cbThursday.setChecked(alarm.getRepetition(Alarm.ALARM_THU));
cbFriday.setChecked(alarm.getRepetition(Alarm.ALARM_FRI));
cbSaturday.setChecked(alarm.getRepetition(Alarm.ALARM_SAT));
cbSunday.setChecked(alarm.getRepetition(Alarm.ALARM_SUN));
}
@ -144,10 +146,11 @@ public class AlarmDetails extends AbstractGBActivity {
private void updateAlarm() {
alarm.setSmartWakeup(supportsSmartWakeup() && cbSmartWakeup.isChecked());
alarm.setRepetition(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked());
int repetitionMask = AlarmUtils.createRepetitionMassk(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked());
alarm.setRepetition(repetitionMask);
alarm.setHour(timePicker.getCurrentHour());
alarm.setMinute(timePicker.getCurrentMinute());
alarm.store();
DBHelper.store(alarm);
}
@Override

View File

@ -19,31 +19,33 @@ package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class ConfigureAlarms extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(ConfigureAlarms.class);
private static final int REQ_CONFIGURE_ALARM = 1;
@ -84,44 +86,48 @@ public class ConfigureAlarms extends AbstractGBActivity {
}
}
/**
* Reads the available alarms from the database and updates the view afterwards.
*/
private void updateAlarmsFromDB() {
Prefs prefs = GBApplication.getPrefs();
int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
int alarmSlots = coordinator.getAlarmSlotCount();
Long deviceId;
List<Alarm> allAlarms = null;
try (DBHandler db = GBApplication.acquireDB()) {
AlarmDao alarmDao = db.getDaoSession().getAlarmDao();
Device dbDevice = DBHelper.findDevice(gbDevice, db.getDaoSession());
deviceId = dbDevice.getId();
QueryBuilder<Alarm> qb = alarmDao.queryBuilder();
qb.where(AlarmDao.Properties.DeviceId.eq(deviceId)).orderAsc(AlarmDao.Properties.Position).limit(alarmSlots - reservedSlots);
allAlarms = qb.build().list();
} catch (Exception e) {
return;
List<Alarm> alarms = DBHelper.getAlarms(getGbDevice());
if (alarms.isEmpty()) {
alarms = AlarmUtils.readAlarmsFromPrefs(getGbDevice());
storeMigratedAlarms(alarms);
}
addMissingAlarms(alarms);
List<GBAlarm> gbAlarms = new ArrayList<>();
if (allAlarms != null) {
for (Alarm alarm : allAlarms) {
gbAlarms.add(new GBAlarm(deviceId, alarm.getPosition(), alarm.getEnabled(),
alarm.getSmartAlarm(), alarm.getRepetition(), alarm.getHour(), alarm.getMinute()));
}
}
int hour = 5;
while (gbAlarms.size() < alarmSlots) {
GBAlarm gbAlarm = new GBAlarm(deviceId, gbAlarms.size(), false, false, 31, hour++, 30);
gbAlarms.add(gbAlarm);
gbAlarm.store();
}
mGBAlarmListAdapter.setAlarmList(gbAlarms);
mGBAlarmListAdapter.setAlarmList(alarms);
mGBAlarmListAdapter.notifyDataSetChanged();
}
private void storeMigratedAlarms(List<Alarm> alarms) {
for (Alarm alarm : alarms) {
DBHelper.store(alarm);
}
}
private void addMissingAlarms(List<Alarm> alarms) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(getGbDevice());
int supportedNumAlarms = coordinator.getAlarmSlotCount();
if (supportedNumAlarms > alarms.size()) {
try (DBHandler db = GBApplication.acquireDB()) {
DaoSession daoSession = db.getDaoSession();
Device device = DBHelper.getDevice(getGbDevice(), daoSession);
User user = DBHelper.getUser(daoSession);
while (supportedNumAlarms > alarms.size()) {
alarms.add(createDefaultAlarm(device, user, alarms.size()));
}
} catch (Exception e) {
LOG.error("Error accessing database", e);
}
}
}
private Alarm createDefaultAlarm(@NonNull Device device, @NonNull User user, int position) {
return new Alarm(device.getId(), user.getId(), position, false, false,0, 6, 30);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@ -133,10 +139,10 @@ public class ConfigureAlarms extends AbstractGBActivity {
return super.onOptionsItemSelected(item);
}
public void configureAlarm(GBAlarm alarm) {
public void configureAlarm(Alarm alarm) {
avoidSendAlarmsToDevice = true;
Intent startIntent = new Intent(getApplicationContext(), AlarmDetails.class);
startIntent.putExtra("alarm", alarm);
startIntent.putExtra(Alarm.EXTRA_ALARM, alarm);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, getGbDevice());
startActivityForResult(startIntent, REQ_CONFIGURE_ALARM);
}

View File

@ -35,33 +35,32 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
/**
* Adapter for displaying GBAlarm instances.
*/
public class GBAlarmListAdapter extends RecyclerView.Adapter<GBAlarmListAdapter.ViewHolder> {
private final Context mContext;
private List<GBAlarm> alarmList;
private ArrayList<Alarm> alarmList;
public GBAlarmListAdapter(Context context) {
this.mContext = context;
}
public void setAlarmList(List<GBAlarm> alarmList) {
this.alarmList = alarmList;
public void setAlarmList(List<Alarm> alarms) {
this.alarmList = new ArrayList<>(alarms);
}
public ArrayList getAlarmList() {
return (ArrayList) alarmList;
public ArrayList<Alarm> getAlarmList() {
return alarmList;
}
public void update(GBAlarm alarm) {
alarm.store();
private void updateInDB(Alarm alarm) {
DBHelper.store(alarm);
}
@NonNull
@ -74,7 +73,7 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter<GBAlarmListAdapter.
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
final GBAlarm alarm = alarmList.get(position);
final Alarm alarm = alarmList.get(position);
holder.alarmDayMonday.setChecked(alarm.getRepetition(Alarm.ALARM_MON));
holder.alarmDayTuesday.setChecked(alarm.getRepetition(Alarm.ALARM_TUE));
@ -88,7 +87,7 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter<GBAlarmListAdapter.
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
alarm.setEnabled(isChecked);
update(alarm);
updateInDB(alarm);
}
});
@ -98,16 +97,15 @@ public class GBAlarmListAdapter extends RecyclerView.Adapter<GBAlarmListAdapter.
((ConfigureAlarms) mContext).configureAlarm(alarm);
}
});
holder.alarmTime.setText(alarm.getTime());
holder.isEnabled.setChecked(alarm.isEnabled());
if (alarm.isSmartWakeup()) {
holder.alarmTime.setText(DateTimeUtils.formatTime(alarm.getHour(), alarm.getMinute()));
holder.isEnabled.setChecked(alarm.getEnabled());
if (alarm.getSmartWakeup()) {
holder.isSmartWakeup.setVisibility(TextView.VISIBLE);
} else {
holder.isSmartWakeup.setVisibility(TextView.GONE);
}
}
@Override
public int getItemCount() {
return alarmList.size();

View File

@ -21,7 +21,6 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -33,6 +32,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@ -44,8 +44,11 @@ import de.greenrobot.dao.query.QueryBuilder;
import de.greenrobot.dao.query.WhereCondition;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescription;
import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescriptionDao;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes;
@ -62,6 +65,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ValidByDate;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
@ -362,6 +366,13 @@ public class DBHelper {
return true;
}
/**
* Finds the corresponding Device entity for the given GBDevice.
* @param gbDevice
* @param session
* @return the corresponding Device entity, or null if none
*/
@Nullable
public static Device findDevice(GBDevice gbDevice, DaoSession session) {
DeviceDao deviceDao = session.getDeviceDao();
Query<Device> query = deviceDao.queryBuilder().where(DeviceDao.Properties.Identifier.eq(gbDevice.getAddress())).build();
@ -561,6 +572,49 @@ public class DBHelper {
return tag;
}
/**
* Returns all user-configurable alarms for the given user and device. The list is sorted by
* {@link Alarm#position}. Calendar events that may also be modeled as alarms are not stored
* in the database and hence not returned by this method.
* @param gbDevice the device for which the alarms shall be loaded
* @return the list of alarms for the given device
*/
@NonNull
public static List<Alarm> getAlarms(@NonNull GBDevice gbDevice) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
Prefs prefs = GBApplication.getPrefs();
// TODO: this alarm reservation is a device dependent detail
int reservedSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
int alarmSlots = coordinator.getAlarmSlotCount();
try (DBHandler db = GBApplication.acquireDB()) {
DaoSession daoSession = db.getDaoSession();
User user = getUser(daoSession);
Device dbDevice = DBHelper.findDevice(gbDevice, daoSession);
if (dbDevice != null) {
AlarmDao alarmDao = daoSession.getAlarmDao();
Long deviceId = dbDevice.getId();
QueryBuilder<Alarm> qb = alarmDao.queryBuilder();
qb.where(
AlarmDao.Properties.UserId.eq(user.getId()),
AlarmDao.Properties.DeviceId.eq(deviceId)).orderAsc(AlarmDao.Properties.Position).limit(alarmSlots - reservedSlots);
return qb.build().list();
}
} catch (Exception e) {
LOG.warn("Error reading alarms from db", e);
}
return Collections.emptyList();
}
public static void store(Alarm alarm) {
try (DBHandler db = GBApplication.acquireDB()) {
DaoSession daoSession = db.getDaoSession();
daoSession.insertOrReplace(alarm);
} catch (Exception e) {
LOG.error("Error acquiring database", e);
}
}
public static void clearSession() {
try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession();

View File

@ -1,215 +0,0 @@
/* Copyright (C) 2015-2018 Andreas Shimokawa, Carsten Pfeiffer, Daniele
Gobbetti
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.impl;
import android.os.Parcel;
import android.support.annotation.NonNull;
import java.util.Calendar;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
public class GBAlarm implements Alarm {
private final int index;
private boolean enabled;
private boolean smartWakeup;
private int repetition;
private int hour;
private int minute;
private long deviceId;
public GBAlarm(Long deviceId, int index, boolean enabled, boolean smartWakeup, int repetition, int hour, int minute) {
this.deviceId = deviceId;
this.index = index;
this.enabled = enabled;
this.smartWakeup = smartWakeup;
this.repetition = repetition;
this.hour = hour;
this.minute = minute;
}
public static GBAlarm createSingleShot(long deviceId, int index, boolean smartWakeup, Calendar calendar) {
return new GBAlarm(deviceId, index, true, smartWakeup, Alarm.ALARM_ONCE, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE));
}
private static GBAlarm readFromParcel(Parcel pc) {
long deviceId = pc.readLong();
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(deviceId, index, enabled, smartWakeup, 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 hashCode() {
return getIndex();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(deviceId);
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);
}
@Override
public int compareTo(@NonNull Alarm another) {
if (this.getIndex() < another.getIndex()) {
return -1;
} else if (this.getIndex() > another.getIndex()) {
return 1;
}
return 0;
}
@Override
public int getIndex() {
return this.index;
}
@Override
public String getTime() {
return String.format(Locale.US, "%02d", this.hour) + ":" + String.format(Locale.US, "%02d", this.minute);
}
public int getHour() {
return this.hour;
}
public int getMinute() {
return this.minute;
}
@Override
public Calendar getAlarmCal() {
Calendar alarm = Calendar.getInstance();
Calendar now = Calendar.getInstance();
alarm.set(Calendar.HOUR_OF_DAY, this.hour);
alarm.set(Calendar.MINUTE, this.minute);
if (now.after(alarm) && repetition == ALARM_ONCE) {
//if the alarm is in the past set it to tomorrow
alarm.add(Calendar.DATE, 1);
}
return alarm;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
@Override
public boolean isSmartWakeup() {
return this.smartWakeup;
}
@Override
public boolean getRepetition(int dow) {
return (this.repetition & dow) > 0;
}
@Override
public int getRepetitionMask() {
return this.repetition;
}
@Override
public boolean isRepetitive() {
return getRepetitionMask() != ALARM_ONCE;
}
public void setSmartWakeup(boolean smartWakeup) {
this.smartWakeup = smartWakeup;
}
public void setRepetition(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) {
this.repetition = (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);
}
public void setHour(int hour) {
this.hour = hour;
}
public void setMinute(int minute) {
this.minute = minute;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void store() {
try (DBHandler db = GBApplication.acquireDB()) {
DaoSession daoSession = db.getDaoSession();
Long userId = DBHelper.getUser(daoSession).getId();
nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm(deviceId, userId, index, enabled, smartWakeup, repetition, hour, minute);
daoSession.insertOrReplace(alarm);
} catch (Exception e) {
// LOG.error("Error acquiring database", e);
}
}
public static final Creator CREATOR = new Creator() {
@Override
public GBAlarm createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
public GBAlarm[] newArray(int size) {
return new GBAlarm[size];
}
};
}

View File

@ -176,7 +176,7 @@ public class GBDeviceService implements DeviceService {
@Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
Intent intent = createIntent().setAction(ACTION_SET_ALARMS)
.putParcelableArrayListExtra(EXTRA_ALARMS, alarms);
.putExtra(EXTRA_ALARMS, alarms);
invokeService(intent);
}

View File

@ -16,11 +16,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.model;
import android.os.Parcelable;
import java.io.Serializable;
import java.util.Calendar;
public interface Alarm extends Serializable {
/**
* The {@link android.os.Bundle} name for transferring pacreled alarms.
*/
String EXTRA_ALARM = "alarm";
public interface Alarm extends Parcelable, Comparable<Alarm> {
byte ALARM_ONCE = 0;
byte ALARM_MON = 1;
byte ALARM_TUE = 2;
@ -30,19 +33,19 @@ public interface Alarm extends Parcelable, Comparable<Alarm> {
byte ALARM_SAT = 32;
byte ALARM_SUN = 64;
int getIndex();
int getPosition();
Calendar getAlarmCal();
boolean getEnabled();
String getTime();
boolean getSmartWakeup();
boolean isEnabled();
boolean isSmartWakeup();
int getRepetitionMask();
int getRepetition();
boolean isRepetitive();
boolean getRepetition(int dow);
int getHour();
int getMinute();
}

View File

@ -548,7 +548,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
}
break;
case ACTION_SET_ALARMS:
ArrayList<Alarm> alarms = intent.getParcelableArrayListExtra(EXTRA_ALARMS);
ArrayList<? extends Alarm> alarms = (ArrayList<? extends Alarm>) intent.getSerializableExtra(EXTRA_ALARMS);
mDeviceSupport.onSetAlarms(alarms);
break;
case ACTION_ENABLE_REALTIME_STEPS: {

View File

@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
@ -430,13 +431,13 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
for (Alarm alarm : alarms) {
if (!alarm.isEnabled())
if (!alarm.getEnabled())
continue;
if (alarm.isSmartWakeup()) //Not available
if (alarm.getSmartWakeup()) //Not available
continue;
Calendar t = alarm.getAlarmCal();
Calendar t = AlarmUtils.toCalendar(alarm);
setAlarm(builder, t);
builder.queue(getQueue());

View File

@ -72,11 +72,11 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.entities.AlarmDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
@ -113,6 +113,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.Upd
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.RealtimeSamplesSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
@ -614,7 +615,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
TransactionBuilder builder = performInitialized("Set alarm");
boolean anyAlarmEnabled = false;
for (Alarm alarm : alarms) {
anyAlarmEnabled |= alarm.isEnabled();
anyAlarmEnabled |= alarm.getEnabled();
queueAlarm(alarm, builder, characteristic);
}
builder.queue(getQueue());
@ -1402,29 +1403,29 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
* @param characteristic
*/
private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) {
Calendar calendar = alarm.getAlarmCal();
Calendar calendar = AlarmUtils.toCalendar(alarm);
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
int maxAlarms = coordinator.getAlarmSlotCount();
if (alarm.getIndex() >= maxAlarms) {
if (alarm.isEnabled()) {
if (alarm.getPosition() >= maxAlarms) {
if (alarm.getEnabled()) {
GB.toast(getContext(), "Only " + maxAlarms + " alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN);
}
return;
}
int base = 0;
if (alarm.isEnabled()) {
if (alarm.getEnabled()) {
base = 128;
}
int daysMask = alarm.getRepetitionMask();
int daysMask = alarm.getRepetition();
if (!alarm.isRepetitive()) {
daysMask = 128;
}
byte[] alarmMessage = new byte[] {
(byte) 0x2, // TODO what is this?
(byte) (base + alarm.getIndex()), // 128 is the base, alarm slot is added
(byte) (base + alarm.getPosition()), // 128 is the base, alarm slot is added
(byte) calendar.get(Calendar.HOUR_OF_DAY),
(byte) calendar.get(Calendar.MINUTE),
(byte) daysMask,
@ -1477,14 +1478,6 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
CalendarEvents upcomingEvents = new CalendarEvents();
List<CalendarEvents.CalendarEvent> mEvents = upcomingEvents.getCalendarEventList(getContext());
Long deviceId;
try (DBHandler handler = GBApplication.acquireDB()) {
DaoSession session = handler.getDaoSession();
deviceId = DBHelper.getDevice(getDevice(), session).getId();
} catch (Exception e) {
LOG.error("Could not acquire DB", e);
return this;
}
int iteration = 0;
for (CalendarEvents.CalendarEvent mEvt : mEvents) {
@ -1494,7 +1487,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
int slotToUse = 2 - iteration;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(mEvt.getBegin());
Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar);
Alarm alarm = AlarmUtils.createSingleShot(slotToUse, false, calendar);
queueAlarm(alarm, builder, characteristic);
iteration++;
}

View File

@ -45,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
@ -277,11 +278,11 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport {
default:
return;
}
Calendar cal = alarms.get(i).getAlarmCal();
Calendar cal = AlarmUtils.toCalendar(alarms.get(i));
builder.write(ctrlCharacteristic, commandWithChecksum(
cmd,
alarms.get(i).isEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1,
alarms.get(i).isEnabled() ? cal.get(Calendar.MINUTE) : -1
alarms.get(i).getEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1,
alarms.get(i).getEnabled() ? cal.get(Calendar.MINUTE) : -1
));
}
builder.queue(getQueue());

View File

@ -56,7 +56,6 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
@ -87,6 +86,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotific
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.FetchActivityOperation;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.UpdateFirmwareOperation;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
@ -560,7 +560,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
TransactionBuilder builder = performInitialized("Set alarm");
boolean anyAlarmEnabled = false;
for (Alarm alarm : alarms) {
anyAlarmEnabled |= alarm.isEnabled();
anyAlarmEnabled |= alarm.getEnabled();
queueAlarm(alarm, builder, characteristic);
}
builder.queue(getQueue());
@ -1134,20 +1134,20 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
* @param characteristic
*/
private void queueAlarm(Alarm alarm, TransactionBuilder builder, BluetoothGattCharacteristic characteristic) {
byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(alarm.getAlarmCal());
byte[] alarmCalBytes = MiBandDateConverter.calendarToRawBytes(AlarmUtils.toCalendar(alarm));
byte[] alarmMessage = new byte[]{
MiBandService.COMMAND_SET_TIMER,
(byte) alarm.getIndex(),
(byte) (alarm.isEnabled() ? 1 : 0),
(byte) alarm.getPosition(),
(byte) (alarm.getEnabled() ? 1 : 0),
alarmCalBytes[0],
alarmCalBytes[1],
alarmCalBytes[2],
alarmCalBytes[3],
alarmCalBytes[4],
alarmCalBytes[5],
(byte) (alarm.isSmartWakeup() ? 30 : 0),
(byte) alarm.getRepetitionMask()
(byte) (alarm.getSmartWakeup() ? 30 : 0),
(byte) alarm.getRepetition()
};
builder.write(characteristic, alarmMessage);
}
@ -1231,15 +1231,6 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
CalendarEvents upcomingEvents = new CalendarEvents();
List<CalendarEvents.CalendarEvent> mEvents = upcomingEvents.getCalendarEventList(getContext());
Long deviceId;
try (DBHandler handler = GBApplication.acquireDB()) {
DaoSession session = handler.getDaoSession();
deviceId = DBHelper.getDevice(getDevice(), session).getId();
} catch (Exception e) {
LOG.error("Could not acquire DB", e);
return;
}
int iteration = 0;
for (CalendarEvents.CalendarEvent mEvt : mEvents) {
if (iteration >= availableSlots || iteration > 2) {
@ -1248,7 +1239,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
int slotToUse = 2 - iteration;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(mEvt.getBegin());
Alarm alarm = GBAlarm.createSingleShot(deviceId, slotToUse, false, calendar);
Alarm alarm = AlarmUtils.createSingleShot(slotToUse, false, calendar);
queueAlarm(alarm, builder, characteristic);
iteration++;
}

View File

@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static org.apache.commons.lang3.math.NumberUtils.min;
@ -188,20 +189,20 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
TransactionBuilder builder = performInitialized("Set alarm");
boolean anyAlarmEnabled = false;
for (Alarm alarm : alarms) {
anyAlarmEnabled |= alarm.isEnabled();
Calendar calendar = alarm.getAlarmCal();
anyAlarmEnabled |= alarm.getEnabled();
Calendar calendar = AlarmUtils.toCalendar(alarm);
int maxAlarms = 3;
if (alarm.getIndex() >= maxAlarms) {
if (alarm.isEnabled()) {
if (alarm.getPosition() >= maxAlarms) {
if (alarm.getEnabled()) {
GB.toast(getContext(), "Only 3 alarms are supported.", Toast.LENGTH_LONG, GB.WARN);
}
return;
}
int daysMask = 0;
if (alarm.isEnabled()) {
daysMask = alarm.getRepetitionMask();
if (alarm.getEnabled()) {
daysMask = alarm.getRepetition();
// Mask for this device starts from sunday and not from monday.
daysMask = (daysMask / 64) + (daysMask >> 1);
}
@ -210,11 +211,11 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
(byte) daysMask,
(byte) calendar.get(Calendar.HOUR_OF_DAY),
(byte) calendar.get(Calendar.MINUTE),
(byte) (alarm.isEnabled() ? 2 : 0), // vibration duration
(byte) (alarm.isEnabled() ? 10 : 0), // vibration count
(byte) (alarm.isEnabled() ? 2 : 0), // unknown
(byte) (alarm.getEnabled() ? 2 : 0), // vibration duration
(byte) (alarm.getEnabled() ? 10 : 0), // vibration count
(byte) (alarm.getEnabled() ? 2 : 0), // unknown
(byte) 0,
(byte) (alarm.getIndex() + 1)
(byte) (alarm.getPosition() + 1)
};
builder.write(ctrlCharacteristic, alarmMessage);
}

View File

@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.watch9.operations.InitOperation;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport {
@ -331,7 +332,7 @@ public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport {
try {
TransactionBuilder builder = performInitialized("setAlarms");
for (Alarm alarm : alarms) {
setAlarm(alarm, alarm.getIndex() + 1, builder);
setAlarm(alarm, alarm.getPosition() + 1, builder);
}
builder.queue(getQueue());
} catch (IOException e) {
@ -352,14 +353,14 @@ public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport {
private void setAlarm(Alarm alarm, int index, TransactionBuilder builder) {
// Shift the GB internal repetition mask to match the device specific one.
byte repetitionMask = (byte) ((alarm.getRepetitionMask() << 1) | (alarm.isRepetitive() ? 0x80 : 0x00));
byte repetitionMask = (byte) ((alarm.getRepetition() << 1) | (alarm.isRepetitive() ? 0x80 : 0x00));
repetitionMask |= (alarm.getRepetition(Alarm.ALARM_SUN) ? 0x01 : 0x00);
if (0 < index && index < 4) {
byte[] alarmValue = new byte[]{(byte) index,
Conversion.toBcd8(alarm.getAlarmCal().get(Calendar.HOUR_OF_DAY)),
Conversion.toBcd8(alarm.getAlarmCal().get(Calendar.MINUTE)),
Conversion.toBcd8(AlarmUtils.toCalendar(alarm).get(Calendar.HOUR_OF_DAY)),
Conversion.toBcd8(AlarmUtils.toCalendar(alarm).get(Calendar.MINUTE)),
repetitionMask,
(byte) (alarm.isEnabled() ? 0x01 : 0x00),
(byte) (alarm.getEnabled() ? 0x01 : 0x00),
0x00 // TODO: Unknown
};
builder.write(getCharacteristic(Watch9Constants.UUID_CHARACTERISTIC_WRITE),

View File

@ -0,0 +1,131 @@
package nodomain.freeyourgadget.gadgetbridge.util;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
/**
* Some utility methods for dealing with Alarms.
*/
public class AlarmUtils {
/**
* Creates an auto-generated (not user-configurable), non-recurring alarm. This alarm
* may not be stored in the database. Some features are not available (e.g. device id, user id).
* @param index
* @param smartWakeup
* @param calendar
* @return
*/
public static nodomain.freeyourgadget.gadgetbridge.model.Alarm createSingleShot(int index, boolean smartWakeup, Calendar calendar) {
return new Alarm(-1, -1, index, true, smartWakeup, Alarm.ALARM_ONCE, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE));
}
/**
* Creates a Calendar object representing the time of the given alarm (not taking the
* day/date into account.
* @param alarm
* @return
*/
public static Calendar toCalendar(nodomain.freeyourgadget.gadgetbridge.model.Alarm alarm) {
Calendar result = Calendar.getInstance();
Calendar now = Calendar.getInstance();
result.set(Calendar.HOUR_OF_DAY, alarm.getHour());
result.set(Calendar.MINUTE, alarm.getMinute());
if (now.after(result) && alarm.getRepetition() == Alarm.ALARM_ONCE) {
//if the alarm is in the past set it to tomorrow
result.add(Calendar.DATE, 1);
}
return result;
}
/**
* Returns a repetition mask suitable for {@link Alarm#repetition}
* @param mon whether the alarm shall repeat every Monday
* @param tue whether the alarm shall repeat every Tuesday
* @param wed whether the alarm shall repeat every Wednesday
* @param thu whether the alarm shall repeat every Thursday
* @param fri whether the alarm shall repeat every Friday
* @param sat whether the alarm shall repeat every Saturday
* @param sun whether the alarm shall repeat every Sunday
* @return the created repetition mask
*/
public static int createRepetitionMassk(boolean mon, boolean tue, boolean wed, boolean thu, boolean fri, boolean sat, boolean sun) {
int repetitionMask = (mon ? Alarm.ALARM_MON : 0) |
(tue ? Alarm.ALARM_TUE : 0) |
(wed ? Alarm.ALARM_WED : 0) |
(thu ? Alarm.ALARM_THU : 0) |
(fri ? Alarm.ALARM_FRI : 0) |
(sat ? Alarm.ALARM_SAT : 0) |
(sun ? Alarm.ALARM_SUN : 0);
return repetitionMask;
}
/**
* Just for backward compatibility, do not call in new code.
* @param gbDevice
* @return
* @deprecated use {@link DBHelper#getAlarms(GBDevice)} instead
*/
@NonNull
public static List<Alarm> readAlarmsFromPrefs(GBDevice gbDevice) {
Prefs prefs = GBApplication.getPrefs();
Set<String> stringAlarms = prefs.getStringSet(MiBandConst.PREF_MIBAND_ALARMS, new HashSet<String>());
List<Alarm> alarms = new ArrayList<>(stringAlarms.size());
try {
DBHandler db = GBApplication.acquireDB();
DaoSession daoSession = db.getDaoSession();
User user = DBHelper.getUser(daoSession);
Device device = DBHelper.getDevice(gbDevice, daoSession);
for (String stringAlarm : stringAlarms) {
alarms.add(createAlarmFromPreference(stringAlarm, device, user));
}
Collections.sort(alarms, AlarmUtils.createComparator());
return alarms;
} catch (Exception e) {
GB.log("Error accessing database", GB.ERROR, e);
return Collections.emptyList();
}
}
private static Alarm createAlarmFromPreference(String fromPreferences, Device device, User user) {
String[] tokens = fromPreferences.split(",");
int index = Integer.parseInt(tokens[0]);
boolean enabled = Boolean.parseBoolean(tokens[1]);
boolean smartWakeup = Boolean.parseBoolean(tokens[2]);
int repetition = Integer.parseInt(tokens[3]);
int hour = Integer.parseInt(tokens[4]);
int minute = Integer.parseInt(tokens[5]);
return new Alarm(device.getId(), user.getId(), index, enabled, smartWakeup, repetition, hour, minute);
}
private static Comparator<Alarm> createComparator() {
return new Comparator<Alarm>() {
@Override
public int compare(Alarm o1, Alarm o2) {
int p1 = o1.getPosition();
int p2 = o2.getPosition();
return Integer.compare(p1, p2);
}
};
}
}

View File

@ -33,6 +33,7 @@ import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
public class DateTimeUtils {
private static SimpleDateFormat DAY_STORAGE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
@ -136,6 +137,11 @@ public class DateTimeUtils {
return HOURS_MINUTES_FORMAT.format(date);
}
public static String formatTime(int hours, int minutes) {
return String.format(Locale.US, "%02d", hours) + ":" + String.format(Locale.US, "%02d", minutes);
}
public static Date todayUTC() {
Calendar cal = getCalendarUTC();
return cal.getTime();