mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-14 19:57:32 +01:00
CalendarReceiver: Convert to ContentObserver
This commit is contained in:
parent
3fe3f9698a
commit
d4a451e8c8
@ -21,8 +21,16 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.provider.CalendarContract;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -48,15 +56,21 @@ import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarEvent;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
public class CalendarReceiver extends BroadcastReceiver {
|
public class CalendarReceiver extends ContentObserver {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CalendarReceiver.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CalendarReceiver.class);
|
||||||
private Hashtable<Long, EventSyncState> eventState = new Hashtable<>();
|
|
||||||
|
|
||||||
private GBDevice mGBDevice;
|
private static final String ACTION_FORCE_SYNC = "FORCE_CALENDAR_SYNC";
|
||||||
|
|
||||||
private class EventSyncState {
|
private final Hashtable<Long, EventSyncState> eventState = new Hashtable<>();
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final GBDevice mGBDevice;
|
||||||
|
private final Handler mSyncHandler;
|
||||||
|
private final BroadcastReceiver mForceSyncReceiver;
|
||||||
|
|
||||||
|
private static class EventSyncState {
|
||||||
private int state;
|
private int state;
|
||||||
private CalendarEvent event;
|
private final CalendarEvent event;
|
||||||
|
|
||||||
EventSyncState(CalendarEvent event, int state) {
|
EventSyncState(CalendarEvent event, int state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
@ -74,10 +88,6 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
public CalendarEvent getEvent() {
|
public CalendarEvent getEvent() {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEvent(CalendarEvent event) {
|
|
||||||
this.event = event;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EventState {
|
private static class EventState {
|
||||||
@ -87,20 +97,45 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
private static final int NEEDS_DELETE = 3;
|
private static final int NEEDS_DELETE = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalendarReceiver(GBDevice gbDevice) {
|
public CalendarReceiver(final Context context, final GBDevice gbDevice) {
|
||||||
LOG.info("Created calendar receiver.");
|
super(new Handler());
|
||||||
|
LOG.info("Created calendar receiver");
|
||||||
|
mContext = context;
|
||||||
mGBDevice = gbDevice;
|
mGBDevice = gbDevice;
|
||||||
onReceive(GBApplication.getContext(), new Intent());
|
mSyncHandler = new Handler();
|
||||||
|
mForceSyncReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
|
LOG.info("Got force sync: {}", intent.getAction());
|
||||||
|
scheduleSync();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mContext.getContentResolver().registerContentObserver(CalendarContract.Events.CONTENT_URI, true, this);
|
||||||
|
// Add a receiver to allow us to quickly force as calendar sync (without having to provide data)
|
||||||
|
LocalBroadcastManager.getInstance(mContext).registerReceiver(mForceSyncReceiver, new IntentFilter(ACTION_FORCE_SYNC));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GBDevice getGBDevice(){
|
public GBDevice getGBDevice() {
|
||||||
return mGBDevice;
|
return mGBDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onChange(boolean selfChange, Uri uri) {
|
||||||
LOG.info("got calendar changed broadcast");
|
super.onChange(selfChange, uri);
|
||||||
List<CalendarEvent> eventList = (new CalendarManager(context, mGBDevice.getAddress())).getCalendarEventList();
|
LOG.info("Got calendar change: {}", uri);
|
||||||
|
scheduleSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleSync() {
|
||||||
|
LOG.debug("Scheduling calendar sync");
|
||||||
|
mSyncHandler.removeCallbacksAndMessages(null);
|
||||||
|
mSyncHandler.postDelayed(this::syncCalendar, 2500L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncCalendar() {
|
||||||
|
List<CalendarEvent> eventList = (new CalendarManager(mContext, mGBDevice.getAddress())).getCalendarEventList();
|
||||||
|
LOG.debug("Syncing {} calendar events", eventList.size());
|
||||||
syncCalendar(eventList);
|
syncCalendar(eventList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +154,6 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
Long deviceId = DBHelper.getDevice(mGBDevice, session).getId();
|
Long deviceId = DBHelper.getDevice(mGBDevice, session).getId();
|
||||||
QueryBuilder<CalendarSyncState> qb = session.getCalendarSyncStateDao().queryBuilder();
|
QueryBuilder<CalendarSyncState> qb = session.getCalendarSyncStateDao().queryBuilder();
|
||||||
|
|
||||||
|
|
||||||
for (CalendarEvent e : eventList) {
|
for (CalendarEvent e : eventList) {
|
||||||
long id = e.getId();
|
long id = e.getId();
|
||||||
eventTable.put(id, e);
|
eventTable.put(id, e);
|
||||||
@ -130,14 +164,13 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
.build().unique();
|
.build().unique();
|
||||||
if (calendarSyncState == null) {
|
if (calendarSyncState == null) {
|
||||||
eventState.put(id, new EventSyncState(e, EventState.NOT_SYNCED));
|
eventState.put(id, new EventSyncState(e, EventState.NOT_SYNCED));
|
||||||
LOG.info("event id=" + id + " is yet unknown to device id=" + deviceId);
|
LOG.info("event id={} is yet unknown to device id={}", id, deviceId);
|
||||||
} else if (calendarSyncState.getHash() == e.hashCode()) {
|
} else if (calendarSyncState.getHash() == e.hashCode()) {
|
||||||
eventState.put(id, new EventSyncState(e, EventState.SYNCED));
|
eventState.put(id, new EventSyncState(e, EventState.SYNCED));
|
||||||
LOG.info("event id=" + id + " is up to date on device id=" + deviceId);
|
LOG.info("event id={} is up to date on device id={}", id, deviceId);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
eventState.put(id, new EventSyncState(e, EventState.NEEDS_UPDATE));
|
eventState.put(id, new EventSyncState(e, EventState.NEEDS_UPDATE));
|
||||||
LOG.info("event id=" + id + " is not up to date on device id=" + deviceId);
|
LOG.info("event id={} is not up to date on device id={}", id, deviceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +180,7 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
for (CalendarSyncState CalendarSyncState : CalendarSyncStateList) {
|
for (CalendarSyncState CalendarSyncState : CalendarSyncStateList) {
|
||||||
if (!eventState.containsKey(CalendarSyncState.getCalendarEntryId())) {
|
if (!eventState.containsKey(CalendarSyncState.getCalendarEntryId())) {
|
||||||
eventState.put(CalendarSyncState.getCalendarEntryId(), new EventSyncState(null, EventState.NEEDS_DELETE));
|
eventState.put(CalendarSyncState.getCalendarEntryId(), new EventSyncState(null, EventState.NEEDS_DELETE));
|
||||||
LOG.info("insert null event for orphaned calendar id=" + CalendarSyncState.getCalendarEntryId() + " for device=" + mGBDevice.getName());
|
LOG.info("insert null event for orphaned calendar id={} for device={}", CalendarSyncState.getCalendarEntryId(), mGBDevice.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +189,10 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
qb = session.getCalendarSyncStateDao().queryBuilder();
|
qb = session.getCalendarSyncStateDao().queryBuilder();
|
||||||
Long i = ids.nextElement();
|
Long i = ids.nextElement();
|
||||||
EventSyncState es = eventState.get(i);
|
EventSyncState es = eventState.get(i);
|
||||||
|
if (es == null) {
|
||||||
|
LOG.error("Failed to get event state for {}", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (eventTable.containsKey(i)) {
|
if (eventTable.containsKey(i)) {
|
||||||
if (es.getState() == EventState.SYNCED) {
|
if (es.getState() == EventState.SYNCED) {
|
||||||
if (!es.getEvent().equals(eventTable.get(i))) {
|
if (!es.getEvent().equals(eventTable.get(i))) {
|
||||||
@ -182,6 +219,10 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
while (ids.hasMoreElements()) {
|
while (ids.hasMoreElements()) {
|
||||||
Long i = ids.nextElement();
|
Long i = ids.nextElement();
|
||||||
EventSyncState es = eventState.get(i);
|
EventSyncState es = eventState.get(i);
|
||||||
|
if (es == null) {
|
||||||
|
LOG.error("Failed to get event state {} for sync", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int syncState = es.getState();
|
int syncState = es.getState();
|
||||||
if (syncState == EventState.NOT_SYNCED || syncState == EventState.NEEDS_UPDATE) {
|
if (syncState == EventState.NOT_SYNCED || syncState == EventState.NEEDS_UPDATE) {
|
||||||
CalendarEvent calendarEvent = es.getEvent();
|
CalendarEvent calendarEvent = es.getEvent();
|
||||||
@ -195,12 +236,12 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
if (calendarEvent.isAllDay()) {
|
if (calendarEvent.isAllDay()) {
|
||||||
//force the all day events to begin at midnight and last N whole days
|
//force the all day events to begin at midnight and last N whole days
|
||||||
Calendar c = GregorianCalendar.getInstance();
|
Calendar c = GregorianCalendar.getInstance();
|
||||||
int numDays = (int)TimeUnit.DAYS.convert(calendarEvent.getEnd()-calendarEvent.getBegin(),
|
int numDays = (int) TimeUnit.DAYS.convert(calendarEvent.getEnd() - calendarEvent.getBegin(),
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
c.setTimeInMillis(calendarEvent.getBegin());
|
c.setTimeInMillis(calendarEvent.getBegin());
|
||||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
//workaround for negative timezones
|
//workaround for negative timezones
|
||||||
if(c.getTimeZone().getRawOffset()<0) c.add(Calendar.DAY_OF_MONTH, 1);
|
if (c.getTimeZone().getRawOffset() < 0) c.add(Calendar.DAY_OF_MONTH, 1);
|
||||||
calendarEventSpec.timestamp = (int) (c.getTimeInMillis() / 1000);
|
calendarEventSpec.timestamp = (int) (c.getTimeInMillis() / 1000);
|
||||||
calendarEventSpec.durationInSeconds = 24 * 60 * 60 * numDays;
|
calendarEventSpec.durationInSeconds = 24 * 60 * 60 * numDays;
|
||||||
}
|
}
|
||||||
@ -228,8 +269,14 @@ public class CalendarReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
mContext.getContentResolver().unregisterContentObserver(this);
|
||||||
|
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mForceSyncReceiver);
|
||||||
|
mSyncHandler.removeCallbacksAndMessages(null);
|
||||||
|
}
|
||||||
|
|
||||||
public static void forceSync() {
|
public static void forceSync() {
|
||||||
final Intent intent = new Intent("FORCE_CALENDAR_SYNC");
|
final Intent intent = new Intent(ACTION_FORCE_SYNC);
|
||||||
intent.setPackage(BuildConfig.APPLICATION_ID);
|
intent.setPackage(BuildConfig.APPLICATION_ID);
|
||||||
GBApplication.getContext().sendBroadcast(intent);
|
GBApplication.getContext().sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
@ -1312,21 +1312,14 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||||||
for (GBDevice deviceWithCalendar : devicesWithCalendar) {
|
for (GBDevice deviceWithCalendar : devicesWithCalendar) {
|
||||||
if (!deviceHasCalendarReceiverRegistered(deviceWithCalendar)) {
|
if (!deviceHasCalendarReceiverRegistered(deviceWithCalendar)) {
|
||||||
if (!(GBApplication.isRunningMarshmallowOrLater() && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_DENIED)) {
|
if (!(GBApplication.isRunningMarshmallowOrLater() && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_DENIED)) {
|
||||||
IntentFilter calendarIntentFilter = new IntentFilter();
|
CalendarReceiver receiver = new CalendarReceiver(this, deviceWithCalendar);
|
||||||
calendarIntentFilter.addAction("android.intent.action.PROVIDER_CHANGED");
|
|
||||||
calendarIntentFilter.addDataScheme("content");
|
|
||||||
calendarIntentFilter.addDataAuthority("com.android.calendar", null);
|
|
||||||
CalendarReceiver receiver = new CalendarReceiver(deviceWithCalendar);
|
|
||||||
ContextCompat.registerReceiver(this, receiver, calendarIntentFilter, ContextCompat.RECEIVER_EXPORTED);
|
|
||||||
mCalendarReceiver.add(receiver);
|
mCalendarReceiver.add(receiver);
|
||||||
// Add a receiver to allow us to quickly force as calendar sync (without having to provide data)
|
|
||||||
ContextCompat.registerReceiver(this, receiver, new IntentFilter("FORCE_CALENDAR_SYNC"), ContextCompat.RECEIVER_EXPORTED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (CalendarReceiver registeredReceiver: mCalendarReceiver){
|
for (CalendarReceiver registeredReceiver: mCalendarReceiver) {
|
||||||
unregisterReceiver(registeredReceiver);
|
registeredReceiver.dispose();
|
||||||
}
|
}
|
||||||
mCalendarReceiver.clear();
|
mCalendarReceiver.clear();
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public class CalendarEventTest extends TestBase {
|
|||||||
GBDevice dummyGBDevice = createDummyGDevice("00:00:01:00:03");
|
GBDevice dummyGBDevice = createDummyGDevice("00:00:01:00:03");
|
||||||
dummyGBDevice.setState(GBDevice.State.INITIALIZED);
|
dummyGBDevice.setState(GBDevice.State.INITIALIZED);
|
||||||
// Device device = DBHelper.getDevice(dummyGBDevice, daoSession);
|
// Device device = DBHelper.getDevice(dummyGBDevice, daoSession);
|
||||||
CalendarReceiver testCR = new CalendarReceiver(dummyGBDevice);
|
CalendarReceiver testCR = new CalendarReceiver(getContext(), dummyGBDevice);
|
||||||
|
|
||||||
testCR.syncCalendar(eventList);
|
testCR.syncCalendar(eventList);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user