diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java index 2ed27c5c6..372010e09 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java @@ -422,6 +422,11 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator { return false; } + @Override + public boolean supportsCalendarAddDelete() { + return supportsCalendarEvents(); + } + @Override public boolean supportsActivityDataFetching() { return false; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java index c58b6e0bb..23dd40ff8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java @@ -505,6 +505,13 @@ public interface DeviceCoordinator { */ boolean supportsCalendarEvents(); + /** + * Indicates whether the device supports adding / deleting individual calendar events. If the + * device supports calendar events, but not add/delete, a full calendar sync is called once + * every time there is any change to any of the calendar events that would be otherwise synced. + */ + boolean supportsCalendarAddDelete(); + /** * Indicates whether the device supports getting a stream of live data. * This can be live HR, steps etc. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java index e11671d44..9673b5fce 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java @@ -121,6 +121,8 @@ public interface EventHandler { void onDeleteCalendarEvent(byte type, long id); + void onCalendarSync(); + /** * Sets the given option in the device, typically with values from the preferences. * The config name is device specific. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java index 77bf357b7..5ba9a9113 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java @@ -112,6 +112,11 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator { @Override public boolean supportsCalendarEvents() { + return true; + } + + @Override + public boolean supportsCalendarAddDelete() { return false; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java index f0988da63..b811bf669 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/zeppos/ZeppOsCoordinator.java @@ -265,6 +265,11 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator { return true; } + @Override + public boolean supportsCalendarAddDelete() { + return true; + } + @Override protected void deleteDevice(@NonNull final GBDevice gbDevice, @NonNull final Device device, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java index 2fdcb8191..ad4697b39 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xiaomi/XiaomiCoordinator.java @@ -230,6 +230,11 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator { return true; } + @Override + public boolean supportsCalendarAddDelete() { + return true; + } + @Override public boolean supportsActivityDataFetching() { return true; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CalendarReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CalendarReceiver.java index a7a0ffef9..764cd25b6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CalendarReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CalendarReceiver.java @@ -116,6 +116,7 @@ public class CalendarReceiver extends BroadcastReceiver { public void syncCalendar(List eventList, DaoSession session) { LOG.info("Syncing with calendar."); Hashtable eventTable = new Hashtable<>(); + Long deviceId = DBHelper.getDevice(mGBDevice, session).getId(); QueryBuilder qb = session.getCalendarSyncStateDao().queryBuilder(); @@ -179,6 +180,9 @@ public class CalendarReceiver extends BroadcastReceiver { private void updateEvents(Long deviceId, DaoSession session) { Enumeration ids = eventState.keys(); + final boolean supportsCalendarAddDelete = mGBDevice.getDeviceCoordinator().supportsCalendarAddDelete(); + boolean anyEventChanged = false; + while (ids.hasMoreElements()) { Long i = ids.nextElement(); EventSyncState es = eventState.get(i); @@ -210,15 +214,27 @@ public class CalendarReceiver extends BroadcastReceiver { calendarEventSpec.calName = calendarEvent.getUniqueCalName(); calendarEventSpec.color = calendarEvent.getColor(); if (syncState == EventState.NEEDS_UPDATE) { - GBApplication.deviceService(mGBDevice).onDeleteCalendarEvent(CalendarEventSpec.TYPE_UNKNOWN, i); + if (supportsCalendarAddDelete) { + GBApplication.deviceService(mGBDevice).onDeleteCalendarEvent(CalendarEventSpec.TYPE_UNKNOWN, i); + } else { + anyEventChanged = true; + } + } + if (supportsCalendarAddDelete) { + GBApplication.deviceService(mGBDevice).onAddCalendarEvent(calendarEventSpec); + } else { + anyEventChanged = true; } - GBApplication.deviceService(mGBDevice).onAddCalendarEvent(calendarEventSpec); es.setState(EventState.SYNCED); eventState.put(i, es); // update db session.insertOrReplace(new CalendarSyncState(null, deviceId, i, es.event.hashCode())); } else if (syncState == EventState.NEEDS_DELETE) { - GBApplication.deviceService(mGBDevice).onDeleteCalendarEvent(CalendarEventSpec.TYPE_UNKNOWN, i); + if (supportsCalendarAddDelete) { + GBApplication.deviceService(mGBDevice).onDeleteCalendarEvent(CalendarEventSpec.TYPE_UNKNOWN, i); + } else { + anyEventChanged = true; + } eventState.remove(i); // delete from db for current device only QueryBuilder qb = session.getCalendarSyncStateDao().queryBuilder(); @@ -226,6 +242,10 @@ public class CalendarReceiver extends BroadcastReceiver { .buildDelete().executeDeleteWithoutDetachingEntities(); } } + + if (!supportsCalendarAddDelete && anyEventChanged) { + GBApplication.deviceService(mGBDevice).onCalendarSync(); + } } public static void forceSync() { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index dbc9fa8a3..dc139e78e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -1168,6 +1168,15 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { } + /** + * Called when the calendar needs to be synced. Only relevant if + * coordinator#supportsCalendarAddDelete is false + */ + @Override + public void onCalendarSync() { + + } + /** * If configuration options can be set on the device, this method * can be overridden and implemented by the device support class. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index fea20d6c1..10a7d7205 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -126,6 +126,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.Alarm; +import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes; import nodomain.freeyourgadget.gadgetbridge.model.SleepState; import nodomain.freeyourgadget.gadgetbridge.model.WearingState; @@ -2705,6 +2706,24 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements } } + @Override + public void onAddCalendarEvent(final CalendarEventSpec calendarEventSpec) { + onCalendarSync(); + } + + public void onDeleteCalendarEvent(final byte type, final long id) { + onCalendarSync(); + } + + public void onCalendarSync() { + final TransactionBuilder builder = createTransactionBuilder("calendar sync"); + sendCalendarEvents(builder); + if (builder.getTransaction().isEmpty()) { + return; + } + builder.queue(getQueue()); + } + protected HuamiSupport sendCalendarEvents(TransactionBuilder builder) { if (characteristicChunked == null) { // all except Mi Band 2 sendCalendarEventsAsAlarms(builder); @@ -2974,6 +2993,9 @@ public abstract class HuamiSupport extends AbstractBTLEDeviceSupport implements case PasswordCapabilityImpl.PREF_PASSWORD_ENABLED: setPassword(builder); break; + case DeviceSettingsPreferenceConst.PREF_SYNC_CALENDAR: + onCalendarSync(); + break; } builder.queue(getQueue()); } catch (IOException e) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java index bbab2636f..a1bc817a2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/XiaomiSupport.java @@ -400,12 +400,19 @@ public class XiaomiSupport extends AbstractDeviceSupport { @Override public void onAddCalendarEvent(final CalendarEventSpec calendarEventSpec) { - calendarService.onAddCalendarEvent(calendarEventSpec); + // we must sync everything + onCalendarSync(); } @Override public void onDeleteCalendarEvent(final byte type, long id) { - calendarService.onDeleteCalendarEvent(type, id); + // we must sync everything + onCalendarSync(); + } + + @Override + public void onCalendarSync() { + calendarService.syncCalendar(); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiCalendarService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiCalendarService.java index f01b11acc..bb4159fe2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiCalendarService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/services/XiaomiCalendarService.java @@ -71,16 +71,6 @@ public class XiaomiCalendarService extends AbstractXiaomiService { return false; } - public void onAddCalendarEvent(final CalendarEventSpec ignoredCalendarEventSpec) { - // we must sync everything - syncCalendar(); - } - - public void onDeleteCalendarEvent(final byte ignoredType, final long ignoredId) { - // we must sync everything - syncCalendar(); - } - public void syncCalendar() { final boolean syncEnabled = GBApplication.getDeviceSpecificSharedPrefs(getSupport().getDevice().getAddress()) .getBoolean(PREF_SYNC_CALENDAR, false);