Limit calendar import to 100 events
This commit is contained in:
@@ -48,8 +48,10 @@ import net.moasdawiki.util.PathUtils;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
@@ -71,8 +73,21 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
private static final Uri EVENT_URI = CalendarContract.Events. CONTENT_URI;
|
private static final Uri EVENT_URI = CalendarContract.Events. CONTENT_URI;
|
||||||
private static final Uri REMINDER_URI = CalendarContract.Reminders.CONTENT_URI;
|
private static final Uri REMINDER_URI = CalendarContract.Reminders.CONTENT_URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alert event 4h before it starts, i.e. at 8pm in the evening before the event day.
|
||||||
|
*/
|
||||||
private static final int REMINDER_BEFORE_EVENT_MINUTES = 4 * 60;
|
private static final int REMINDER_BEFORE_EVENT_MINUTES = 4 * 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import maximum 100 events. If there are more events found, take the 100 upcoming events
|
||||||
|
* sorted by date.
|
||||||
|
*
|
||||||
|
* Android has a global event limitation of 500 events. If more than 500 events are created,
|
||||||
|
* Android throws errors with message "Maximum limit of concurrent alarms 500 reached" and
|
||||||
|
* ignores some events.
|
||||||
|
*/
|
||||||
|
private static final int MAX_EVENT_COUNT = 100;
|
||||||
|
|
||||||
private final ContentResolver contentResolver;
|
private final ContentResolver contentResolver;
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
@SuppressWarnings("SameParameterValue")
|
||||||
@@ -84,13 +99,19 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
|
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
|
||||||
Log.d(TAG, "Begin of onPerformSync()");
|
Log.d(TAG, "Begin of onPerformSync()");
|
||||||
List<TerminTransformer.Event> events = getWikiEvents();
|
// collect and filter events
|
||||||
|
List<TerminTransformer.Event> rawEvents = getWikiEvents();
|
||||||
|
fillEmptyDateFields(rawEvents);
|
||||||
|
List<TerminTransformer.Event> events = filterEvents(rawEvents);
|
||||||
|
|
||||||
|
// update Android calendar
|
||||||
String calendarId = createCalendar();
|
String calendarId = createCalendar();
|
||||||
if (calendarId != null) {
|
if (calendarId != null) {
|
||||||
deleteAllEvents(calendarId);
|
deleteAllEvents(calendarId);
|
||||||
addEvents(calendarId, events);
|
addEvents(calendarId, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inform user about completed update
|
||||||
Handler handler = new Handler(Looper.getMainLooper());
|
Handler handler = new Handler(Looper.getMainLooper());
|
||||||
handler.post(() -> {
|
handler.post(() -> {
|
||||||
Toast toast = Toast.makeText(getContext(), R.string.calendar_sync_finished, Toast.LENGTH_SHORT);
|
Toast toast = Toast.makeText(getContext(), R.string.calendar_sync_finished, Toast.LENGTH_SHORT);
|
||||||
@@ -116,6 +137,65 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills empty day, month, and year fields in all events.
|
||||||
|
*/
|
||||||
|
private void fillEmptyDateFields(@NotNull List<TerminTransformer.Event> events) {
|
||||||
|
TimeZone utc = TimeZone.getTimeZone("UTC");
|
||||||
|
Calendar calendar = Calendar.getInstance(utc);
|
||||||
|
for (TerminTransformer.Event event : events) {
|
||||||
|
if (event.dateFields.day == null) {
|
||||||
|
event.dateFields.day = 1;
|
||||||
|
}
|
||||||
|
if (event.dateFields.month == null) {
|
||||||
|
event.dateFields.month = 1;
|
||||||
|
}
|
||||||
|
if (event.dateFields.year == null) {
|
||||||
|
event.dateFields.year = calendar.get(Calendar.YEAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the number of events if more than MAX_EVENT_COUNT, only keep events in the near future.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private List<TerminTransformer.Event> filterEvents(@NotNull List<TerminTransformer.Event> rawEvents) {
|
||||||
|
if (rawEvents.size() <= MAX_EVENT_COUNT) {
|
||||||
|
return rawEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by month and day;
|
||||||
|
// ignore year because events repeat every year
|
||||||
|
List<TerminTransformer.Event> sortedEvents = new ArrayList<>(rawEvents);
|
||||||
|
sortedEvents.sort(Comparator.comparingInt((TerminTransformer.Event event) -> event.dateFields.month).thenComparingInt(event -> event.dateFields.day));
|
||||||
|
|
||||||
|
// keep next MAX_EVENT_COUNT events from today onwards
|
||||||
|
List<TerminTransformer.Event> result = new ArrayList<>(MAX_EVENT_COUNT);
|
||||||
|
// find first event in future
|
||||||
|
TimeZone utc = TimeZone.getTimeZone("UTC");
|
||||||
|
Calendar calendar = Calendar.getInstance(utc);
|
||||||
|
int index = 0;
|
||||||
|
while (index < sortedEvents.size() - 1
|
||||||
|
&& (sortedEvents.get(index).dateFields.month < calendar.get(Calendar.MONTH) + 1
|
||||||
|
|| sortedEvents.get(index).dateFields.month == calendar.get(Calendar.MONTH) + 1
|
||||||
|
&& sortedEvents.get(index).dateFields.day < calendar.get(Calendar.DAY_OF_MONTH))) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
// copy events until end of year
|
||||||
|
while (result.size() < MAX_EVENT_COUNT && index < sortedEvents.size() - 1) {
|
||||||
|
result.add(sortedEvents.get(index));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
// copy events in new year
|
||||||
|
index = 0;
|
||||||
|
while (result.size() < MAX_EVENT_COUNT && index < sortedEvents.size() - 1) {
|
||||||
|
result.add(sortedEvents.get(index));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Uri buildUri(@NotNull Uri uri) {
|
private Uri buildUri(@NotNull Uri uri) {
|
||||||
return uri.buildUpon()
|
return uri.buildUpon()
|
||||||
@@ -155,7 +235,6 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
cv.put(CalendarContract.Calendars.NAME, CALENDAR_NAME);
|
cv.put(CalendarContract.Calendars.NAME, CALENDAR_NAME);
|
||||||
String displayName = getContext().getString(R.string.calendar_display_name);
|
String displayName = getContext().getString(R.string.calendar_display_name);
|
||||||
cv.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, displayName);
|
cv.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, displayName);
|
||||||
//cv.put(CalendarContract.Calendars.CALENDAR_COLOR, 0xEA8561);
|
|
||||||
cv.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_READ);
|
cv.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_READ);
|
||||||
cv.put(CalendarContract.Calendars.OWNER_ACCOUNT, ACCOUNT_NAME);
|
cv.put(CalendarContract.Calendars.OWNER_ACCOUNT, ACCOUNT_NAME);
|
||||||
cv.put(CalendarContract.Calendars.VISIBLE, 1);
|
cv.put(CalendarContract.Calendars.VISIBLE, 1);
|
||||||
@@ -191,8 +270,8 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all events from the event list. The first occurrence is in the current year, the events
|
* Adds up to 100 events from the event list.
|
||||||
* are repeated every year.
|
* The first occurrence is in the current year, the events are repeated every year.
|
||||||
*/
|
*/
|
||||||
private void addEvents(@NotNull String calendarId, @NotNull List<TerminTransformer.Event> events) {
|
private void addEvents(@NotNull String calendarId, @NotNull List<TerminTransformer.Event> events) {
|
||||||
Log.d(TAG, "Create calendar events");
|
Log.d(TAG, "Create calendar events");
|
||||||
@@ -214,7 +293,7 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
* Adds a single event to the calendar.
|
* Adds a single event to the calendar.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private String addEvent(@NotNull String calendarId, @Nullable Integer day, @Nullable Integer month, @Nullable Integer year, @NotNull String title, @NotNull String description) {
|
private String addEvent(@NotNull String calendarId, int day, int month, int year, @NotNull String title, @NotNull String description) {
|
||||||
Log.d(TAG, "Create calendar event: day=" + day + ", month=" + month + ", year=" + year
|
Log.d(TAG, "Create calendar event: day=" + day + ", month=" + month + ", year=" + year
|
||||||
+ ", title=" + title + ", description=" + description);
|
+ ", title=" + title + ", description=" + description);
|
||||||
ContentValues cv = new ContentValues();
|
ContentValues cv = new ContentValues();
|
||||||
@@ -224,18 +303,8 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
|
|
||||||
TimeZone utc = TimeZone.getTimeZone("UTC");
|
TimeZone utc = TimeZone.getTimeZone("UTC");
|
||||||
Calendar beginTime = Calendar.getInstance(utc);
|
Calendar beginTime = Calendar.getInstance(utc);
|
||||||
if (day == null) {
|
|
||||||
day = 1;
|
|
||||||
}
|
|
||||||
if (month == null) {
|
|
||||||
month = 1;
|
|
||||||
}
|
|
||||||
if (year == null) {
|
|
||||||
year = beginTime.get(Calendar.YEAR);
|
|
||||||
}
|
|
||||||
beginTime.clear();
|
beginTime.clear();
|
||||||
beginTime.set(year, month - 1, day);
|
beginTime.set(year, month - 1, day);
|
||||||
|
|
||||||
cv.put(CalendarContract.Events.DTSTART, beginTime.getTimeInMillis());
|
cv.put(CalendarContract.Events.DTSTART, beginTime.getTimeInMillis());
|
||||||
cv.put(CalendarContract.Events.DURATION, "PT1D");
|
cv.put(CalendarContract.Events.DURATION, "PT1D");
|
||||||
cv.put(CalendarContract.Events.ALL_DAY, 1);
|
cv.put(CalendarContract.Events.ALL_DAY, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user