From 4521bc7d4e994efef03c510f70b310e80b59009b Mon Sep 17 00:00:00 2001 From: jens Date: Sun, 7 Jan 2024 15:15:56 +0100 Subject: [PATCH] Calendar trigger --- .../ActivityManageTriggerCalendar.java | 58 +++++++--- .../java/com/jens/automation2/Trigger.java | 53 ++++++--- .../receivers/CalendarReceiver.java | 109 ++++++++++++++++-- .../activity_manage_trigger_calendar.xml | 34 +++++- app/src/main/res/values/strings.xml | 3 + 5 files changed, 219 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java index f6343ab..097c093 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java @@ -33,7 +33,7 @@ import java.util.List; public class ActivityManageTriggerCalendar extends Activity { - CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent, calendarEvaluateAllDayEvent; + CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent, chkCalendarEvaluateAllDayEvent, chkCalendarEvaluateReoccurring, chkCalendarReoccurring; Spinner spinnerCalendarTitleDirection, spinnerCalendarLocationDirection, spinnerCalendarDescriptionDirection; EditText etCalendarTitle, etCalendarLocation, etCalendarDescription; LinearLayout llCalendarSelection; @@ -53,7 +53,7 @@ public class ActivityManageTriggerCalendar extends Activity Miscellaneous.setDisplayLanguage(this); setContentView(R.layout.activity_manage_trigger_calendar); - //TODO: Hint text about multiple rule execution + //TODO: Hint text about multiple rule execution and reoccurring events always being included in the query chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive); spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection); @@ -65,7 +65,9 @@ public class ActivityManageTriggerCalendar extends Activity chkCalendarAvailabilityTentative = (CheckBox)findViewById(R.id.chkCalendarAvailabilityTentative); chkCalendarAvailabilityOutOfOffice = (CheckBox)findViewById(R.id.chkCalendarAvailabilityOutOfOffice); chkCalendarAvailabilityWorkingElsewhere = (CheckBox)findViewById(R.id.chkCalendarAvailabilityWorkingElsewhere); - calendarEvaluateAllDayEvent = (CheckBox)findViewById(R.id.calendarEvaluateAllDayEvent); + chkCalendarEvaluateAllDayEvent = (CheckBox)findViewById(R.id.chkCalendarEvaluateAllDayEvent); + chkCalendarEvaluateReoccurring = (CheckBox)findViewById(R.id.chkCalendarEvaluateReoccurring); + chkCalendarReoccurring = (CheckBox)findViewById(R.id.chkCalendarReoccurring); tvMissingCalendarHint = (TextView) findViewById(R.id.tvMissingCalendarHint); @@ -91,9 +93,9 @@ public class ActivityManageTriggerCalendar extends Activity spinnerCalendarDescriptionDirection.setAdapter(directionSpinnerAdapter); directionSpinnerAdapter.notifyDataSetChanged(); - calendarEvaluateAllDayEvent.setChecked(false); + chkCalendarEvaluateAllDayEvent.setChecked(false); chkCalendarAllDayEvent.setEnabled(false); - calendarEvaluateAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() + chkCalendarEvaluateAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) @@ -102,6 +104,17 @@ public class ActivityManageTriggerCalendar extends Activity } }); + chkCalendarEvaluateReoccurring.setChecked(false); + chkCalendarReoccurring.setEnabled(false); + chkCalendarEvaluateReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() + { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) + { + chkCalendarReoccurring.setEnabled(checked); + } + }); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, ActivityManageTriggerCalendar.this) || ActivityPermissions.havePermission(Manifest.permission.WRITE_CALENDAR, ActivityManageTriggerCalendar.this)) @@ -157,6 +170,18 @@ public class ActivityManageTriggerCalendar extends Activity } }); + chkCalendarReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() + { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) + { + if(checked) + chkCalendarReoccurring.setText(R.string.reoccurringTrue); + else + chkCalendarReoccurring.setText(R.string.reoccurringFalse); + } + }); + bSaveTriggerCalendar.setOnClickListener(new View.OnClickListener() { @Override @@ -199,8 +224,10 @@ public class ActivityManageTriggerCalendar extends Activity titleDir + Trigger.triggerParameter2Split + title + Trigger.triggerParameter2Split + descriptionDir + Trigger.triggerParameter2Split + description + Trigger.triggerParameter2Split + locationDir + Trigger.triggerParameter2Split + location + Trigger.triggerParameter2Split + - String.valueOf(calendarEvaluateAllDayEvent.isChecked()) + Trigger.triggerParameter2Split + + String.valueOf(chkCalendarEvaluateAllDayEvent.isChecked()) + Trigger.triggerParameter2Split + String.valueOf(chkCalendarAllDayEvent.isChecked()) + Trigger.triggerParameter2Split + + String.valueOf(chkCalendarEvaluateReoccurring.isChecked()) + Trigger.triggerParameter2Split + + String.valueOf(chkCalendarReoccurring.isChecked()) + Trigger.triggerParameter2Split + Miscellaneous.explode(separator, availabilityList.toArray(new String[availabilityList.size()])) + Trigger.triggerParameter2Split + Miscellaneous.explode(separator, selectedCalendarsIdArray.toArray(new String[selectedCalendarsIdArray.size()])); @@ -261,8 +288,10 @@ public class ActivityManageTriggerCalendar extends Activity 5 = location 6 = evaluate all day event 7 = all day event - 8 = availability list - 9 = calendars list + 8 = evaluate reoccurring + 9 = reoccurring + 10 = availability list + 11 = calendars list */ for (int i = 0; i < directions.length; i++) @@ -281,12 +310,15 @@ public class ActivityManageTriggerCalendar extends Activity etCalendarDescription.setText(input[3]); etCalendarLocation.setText(input[5]); - calendarEvaluateAllDayEvent.setChecked(Boolean.parseBoolean(input[6])); + chkCalendarEvaluateAllDayEvent.setChecked(Boolean.parseBoolean(input[6])); chkCalendarAllDayEvent.setChecked(Boolean.parseBoolean(input[7])); + chkCalendarEvaluateReoccurring.setChecked(Boolean.parseBoolean(input[8])); + chkCalendarReoccurring.setChecked(Boolean.parseBoolean(input[9])); + String[] availabilities = null; - if (!StringUtils.isEmpty(input[8])) - availabilities = input[8].split(separator); + if (!StringUtils.isEmpty(input[10])) + availabilities = input[10].split(separator); if (availabilities != null) { @@ -306,8 +338,8 @@ public class ActivityManageTriggerCalendar extends Activity } String[] calendars = null; - if (!StringUtils.isEmpty(input[9])) - calendars = input[9].split(separator); + if (!StringUtils.isEmpty(input[11])) + calendars = input[11].split(separator); if (calendars != null) { diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index 8ebb9c1..e6bd87a 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -622,7 +622,7 @@ public class Trigger try { String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split); - List calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), false); + List calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), true,false); /* 0 = titleDirection @@ -675,19 +675,21 @@ public class Trigger public boolean checkCalendarEvent(CalendarReceiver.CalendarEvent event, boolean ignoreActive) { String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split); - List calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), false); + List calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), true,false); /* - 0 = titleDirection - 1 = title; - 2 = descriptionDirection + 0 = titleDir + 1 = title + 2 = descriptionDir 3 = description - 4 = eventLocationDirection - 5 = eventLocation + 4 = locationDir + 5 = location 6 = evaluate all day event 7 = all day event - 8 = availabilityList - 9 = calendarList + 8 = evaluate reoccurring + 9 = reoccurring + 10 = availability list + 11 = calendars list */ boolean isActive = getTriggerParameter(); @@ -733,9 +735,18 @@ public class Trigger } } - if (!StringUtils.isEmpty(conditions[8])) + if (Boolean.parseBoolean(conditions[8])) { - String[] availabilities = conditions[8].split(ActivityManageTriggerCalendar.separator); + if (Boolean.parseBoolean(conditions[9]) != event.reoccurring) + { + Miscellaneous.logEvent("i", "CalendarCheck", "Reoccurring setting does not match.", 5); + return false; + } + } + + if (!StringUtils.isEmpty(conditions[10])) + { + String[] availabilities = conditions[10].split(ActivityManageTriggerCalendar.separator); if (availabilities.length > 0) { if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true)) @@ -746,9 +757,9 @@ public class Trigger } } - if (!StringUtils.isEmpty(conditions[9])) + if (!StringUtils.isEmpty(conditions[11])) { - String[] calendars = conditions[9].split(ActivityManageTriggerCalendar.separator); + String[] calendars = conditions[11].split(ActivityManageTriggerCalendar.separator); if (calendars.length > 0) { if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true)) @@ -1998,11 +2009,19 @@ public class Trigger returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventFalse) + ", "); } - if (!StringUtils.isEmpty(conditions[8])) - returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[8] + ", "); + if(Boolean.parseBoolean(conditions[8])) + { + if (Boolean.parseBoolean(conditions[9])) + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.reoccurringTrue) + ", "); + else + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.reoccurringFalse) + ", "); + } - if (!StringUtils.isEmpty(conditions[9])) - returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[9]); + if (!StringUtils.isEmpty(conditions[10])) + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[10] + ", "); + + if (!StringUtils.isEmpty(conditions[11])) + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[11]); if (returnString.toString().endsWith(", ")) returnString.delete(returnString.length() - 2, returnString.length()); diff --git a/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java b/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java index 0e501b1..935ed8c 100644 --- a/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java @@ -9,6 +9,7 @@ import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.provider.CalendarContract; import android.util.Log; import androidx.annotation.NonNull; @@ -39,6 +40,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis static List calendarsCache = null; static List calendarEventsCache = null; + static List calendarEventsReoccuringCache = null; static Timer timer = null; static TimerTask timerTask = null; @@ -166,7 +168,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis public String location; public String availability; public Calendar start, end; - public boolean allDay; + public boolean allDay, reoccurring; public boolean isCurrentlyActive() { @@ -223,7 +225,8 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis cursor = context.getContentResolver().query( Uri.parse("content://com.android.calendar/calendars"), - new String[]{ "_id", "calendar_displayName", "ownerAccount", }, + + new String[]{ CalendarContract.Calendars._ID, CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CalendarContract.Calendars.OWNER_ACCOUNT, }, null, null, null); cursor.moveToFirst(); @@ -256,7 +259,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis return calendarsCache; } - public static List readCalendarEvents(Context context, boolean includePastEvents) + public static List readCalendarEvents(Context context, boolean includeReoccurring, boolean includePastEvents) { if(calendarEventsCache == null) { @@ -266,7 +269,17 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis cursor = context.getContentResolver().query( Uri.parse("content://com.android.calendar/events"), - new String[] { "calendar_id", "_id", "title", "description", "allDay", "dtstart", "dtend", "eventLocation", "availability" }, + new String[] { + CalendarContract.Events.CALENDAR_ID, + CalendarContract.Events._ID, + CalendarContract.Events.TITLE, + CalendarContract.Events.DESCRIPTION, + CalendarContract.Events.ALL_DAY, + CalendarContract.Events.DTSTART, + CalendarContract.Events.DTEND, + CalendarContract.Events.EVENT_LOCATION, + CalendarContract.Events.AVAILABILITY + }, null, null, null); cursor.moveToFirst(); @@ -299,6 +312,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis event.end = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(6))); event.location = cursor.getString(7); event.availability = cursor.getString(8); + event.reoccurring = false; if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis()) calendarEventsCache.add(event); @@ -313,6 +327,87 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis } + if(includeReoccurring && calendarEventsReoccuringCache == null) + { + calendarEventsReoccuringCache = new ArrayList<>(); + + Cursor cursor; + + Calendar queryStart, queryEnd; + if(includePastEvents) + queryStart = Miscellaneous.calendarFromLong(0); + else + queryStart = Calendar.getInstance(); + + queryEnd = Calendar.getInstance(); + queryEnd.add(Calendar.YEAR, 1); + + cursor = context.getContentResolver().query( + Uri.parse("content://com.android.calendar/instances/when/" + queryStart.getTimeInMillis() + "/" + queryEnd.getTimeInMillis()), + new String[] { + CalendarContract.Instances.CALENDAR_ID, + CalendarContract.Instances._ID, + CalendarContract.Instances.TITLE, + CalendarContract.Instances.DESCRIPTION, + CalendarContract.Instances.ALL_DAY, + CalendarContract.Instances.BEGIN, + CalendarContract.Instances.END, +// CalendarContract.Instances.DTSTART, +// CalendarContract.Instances.DTEND, + CalendarContract.Instances.EVENT_LOCATION, + CalendarContract.Instances.AVAILABILITY + }, + null, null, null); + + cursor.moveToFirst(); + // fetching calendars name + String CNames[] = new String[cursor.getCount()]; + + Calendar now = Calendar.getInstance(); + + for (int i = 0; i < CNames.length; i++) + { + try + { + CalendarEvent event = new CalendarEvent(); + event.calendarId = Integer.parseInt(cursor.getString(0)); + + for(AndroidCalendar cal : readCalendars(context)) + { + if(cal.calendarId == event.calendarId) + { + event.calendar = cal; + break; + } + } + + event.eventId = cursor.getString(1); + event.title = cursor.getString(2); + event.description = cursor.getString(3); + event.allDay = cursor.getString(4).equals("1"); + event.start = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(5))); + event.end = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(6))); + event.location = cursor.getString(7); + event.availability = cursor.getString(8); + event.reoccurring = true; + + if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis()) + { + // For the moment keeping separate records to some extent + calendarEventsReoccuringCache.add(event); + calendarEventsCache.add(event); + } + } + catch (Exception e) + {} + cursor.moveToNext(); + } + + if(cursor != null) + cursor.close(); + + } + return calendarEventsCache; } @@ -363,7 +458,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis if(nextWakeup == null) { - readCalendarEvents(Miscellaneous.getAnyContext(), false); + readCalendarEvents(Miscellaneous.getAnyContext(), true,false); calculateNextWakeup(); } @@ -395,7 +490,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis private static void calculateNextWakeup() { Calendar now = Calendar.getInstance(); - List events = readCalendarEvents(Miscellaneous.getAnyContext(), false); + List events = readCalendarEvents(Miscellaneous.getAnyContext(), true, false); if (events.size() == 0) { @@ -479,7 +574,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis public static boolean mayRuleStillBeActivatedForPendingCalendarEvents(Rule rule) { - for(CalendarEvent event : readCalendarEvents(Miscellaneous.getAnyContext(), false)) + for(CalendarEvent event : readCalendarEvents(Miscellaneous.getAnyContext(), true,false)) { for(Trigger t : rule.getTriggerSet()) { diff --git a/app/src/main/res/layout/activity_manage_trigger_calendar.xml b/app/src/main/res/layout/activity_manage_trigger_calendar.xml index ee0b6e4..2b7891d 100644 --- a/app/src/main/res/layout/activity_manage_trigger_calendar.xml +++ b/app/src/main/res/layout/activity_manage_trigger_calendar.xml @@ -176,7 +176,7 @@ android:background="#aa000000" /> + + + + + + + + + + + + Evaluate An error occur occured while loading values. Enter valid data into the parameter fields. + event is not reoccurring + event is reoccurring + reoccurring \ No newline at end of file