diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml
index cf6a6119..38903380 100644
--- a/app/src/apkFlavor/AndroidManifest.xml
+++ b/app/src/apkFlavor/AndroidManifest.xml
@@ -144,7 +144,12 @@
-
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java
index e171bf35..6bc98c3c 100644
--- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java
+++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java
@@ -18,13 +18,14 @@ import androidx.annotation.Nullable;
import com.jens.automation2.receivers.CalendarReceiver;
-import java.sql.Array;
+import org.apache.commons.lang3.StringUtils;
+
import java.util.ArrayList;
import java.util.List;
public class ActivityManageTriggerCalendar extends Activity
{
- CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere;
+ CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent;
Spinner spinnerCalendarTitleDirection, spinnerCalendarLocationDirection, spinnerCalendarDescriptionDirection;
EditText etCalendarTitle, etCalendarLocation, etCalendarDescription;
LinearLayout llCalendarSelection;
@@ -47,6 +48,7 @@ public class ActivityManageTriggerCalendar extends Activity
spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection);
spinnerCalendarLocationDirection = (Spinner)findViewById(R.id.spinnerCalendarLocationDirection);
spinnerCalendarDescriptionDirection = (Spinner)findViewById(R.id.spinnerCalendarDescriptionDirection);
+ chkCalendarAllDayEvent = (CheckBox)findViewById(R.id.chkCalendarAllDayEvent);
chkCalendarAvailabilityBusy = (CheckBox)findViewById(R.id.chkCalendarAvailabilityBusy);
chkCalendarAvailabilityFree = (CheckBox)findViewById(R.id.chkCalendarAvailabilityFree);
chkCalendarAvailabilityTentative = (CheckBox)findViewById(R.id.chkCalendarAvailabilityTentative);
@@ -80,7 +82,7 @@ public class ActivityManageTriggerCalendar extends Activity
for(CalendarReceiver.AndroidCalendar cal : CalendarReceiver.readCalendars(ActivityManageTriggerCalendar.this))
{
CheckBox oneCalCheckbox = new CheckBox(ActivityManageTriggerCalendar.this);
- oneCalCheckbox.setText(cal.displayName);
+ oneCalCheckbox.setText(cal.toString());
oneCalCheckbox.setTag(cal);
llCalendarSelection.addView(oneCalCheckbox);
checkboxesCalendars.add(oneCalCheckbox);
@@ -98,6 +100,18 @@ public class ActivityManageTriggerCalendar extends Activity
}
});
+ chkCalendarAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
+ {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
+ {
+ if(checked)
+ chkCalendarAllDayEvent.setText(getResources().getString(R.string.allDayEventTrue));
+ else
+ chkCalendarAllDayEvent.setText(getResources().getString(R.string.allDayEventFalse));
+ }
+ });
+
bSaveTriggerCalendar.setOnClickListener(new View.OnClickListener()
{
@Override
@@ -140,6 +154,7 @@ 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(chkCalendarAllDayEvent.isChecked()) + Trigger.triggerParameter2Split +
Miscellaneous.explode(separator, availabilityList.toArray(new String[availabilityList.size()])) + Trigger.triggerParameter2Split +
Miscellaneous.explode(separator, selectedCalendarsIdArray.toArray(new String[selectedCalendarsIdArray.size()]));
@@ -174,8 +189,9 @@ public class ActivityManageTriggerCalendar extends Activity
3 = description
4 = locationDir
5 = location
- 6 = availability list
- 7 = calendars list
+ 6 = all day event
+ 7 = availability list
+ 8 = calendars list
*/
for(int i = 0; i < directions.length; i++)
@@ -194,52 +210,65 @@ public class ActivityManageTriggerCalendar extends Activity
etCalendarDescription.setText(input[3]);
etCalendarLocation.setText(input[5]);
- String[] availabilities = input[6].split(separator);
- String[] calendars = input[7].split(separator);
+ chkCalendarAllDayEvent.setChecked(Boolean.parseBoolean(input[6]));
- for(String avail : availabilities)
- {
- if(Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_BUSY)
- chkCalendarAvailabilityBusy.setChecked(true);
- else if(Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_FREE)
- chkCalendarAvailabilityFree.setChecked(true);
- else if(Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_TENTATIVE)
- chkCalendarAvailabilityTentative.setChecked(true);
- else if(Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE)
- chkCalendarAvailabilityOutOfOffice.setChecked(true);
- else if(Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE)
- chkCalendarAvailabilityWorkingElsewhere.setChecked(true);
- }
+ String[] availabilities = null;
+ if(!StringUtils.isEmpty(input[7]))
+ availabilities = input[7].split(separator);
- List usedCalendarIDs = new ArrayList<>();
- List unusedCalendarIDs = new ArrayList<>();
- for(CheckBox checkbox : checkboxesCalendars)
+ String[] calendars = null;
+ if(!StringUtils.isEmpty(input[8]))
+ calendars = input[8].split(separator);
+
+ if(availabilities != null)
{
- int id = ((CalendarReceiver.AndroidCalendar)checkbox.getTag()).calendarId;
- for(String calId : calendars)
+ for (String avail : availabilities)
{
- if(calId.equals(String.valueOf(id)))
- {
- usedCalendarIDs.add(String.valueOf(id));
- checkbox.setChecked(true);
- break;
- }
+ if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_BUSY)
+ chkCalendarAvailabilityBusy.setChecked(true);
+ else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_FREE)
+ chkCalendarAvailabilityFree.setChecked(true);
+ else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_TENTATIVE)
+ chkCalendarAvailabilityTentative.setChecked(true);
+ else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE)
+ chkCalendarAvailabilityOutOfOffice.setChecked(true);
+ else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE)
+ chkCalendarAvailabilityWorkingElsewhere.setChecked(true);
}
}
- for(String calId : calendars)
- {
- if(!Miscellaneous.arraySearch((ArrayList) usedCalendarIDs, calId, false, true))
- unusedCalendarIDs.add(calId);
- }
- if(unusedCalendarIDs.size() > 0)
+
+ if(calendars != null)
{
+ List usedCalendarIDs = new ArrayList<>();
+ List unusedCalendarIDs = new ArrayList<>();
+ for (CheckBox checkbox : checkboxesCalendars)
+ {
+ int id = ((CalendarReceiver.AndroidCalendar) checkbox.getTag()).calendarId;
+ for (String calId : calendars)
+ {
+ if (calId.equals(String.valueOf(id)))
+ {
+ usedCalendarIDs.add(String.valueOf(id));
+ checkbox.setChecked(true);
+ break;
+ }
+ }
+ }
+ for (String calId : calendars)
+ {
+ if (!Miscellaneous.arraySearch((ArrayList) usedCalendarIDs, calId, false, true))
+ unusedCalendarIDs.add(calId);
+ }
+ if (unusedCalendarIDs.size() > 0)
+ {
/*
A calendar has been configured that has been deleted since. We cannot resolve it.
It will be removed with the next save, but we should inform this user
of these circumstances.
*/
- tvMissingCalendarHint.setText(String.format(getResources().getString(R.string.calendarsMissingHint), Miscellaneous.explode(", ", (ArrayList) unusedCalendarIDs)));
+ tvMissingCalendarHint.setText(String.format(getResources().getString(R.string.calendarsMissingHint), Miscellaneous.explode(", ", (ArrayList) unusedCalendarIDs)));
+ }
}
}
}
diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java
index 4b47da7f..2f12e428 100644
--- a/app/src/main/java/com/jens/automation2/Trigger.java
+++ b/app/src/main/java/com/jens/automation2/Trigger.java
@@ -631,8 +631,9 @@ public class Trigger
3 = description
4 = eventLocationDirection
5 = eventLocation
- 6 = availabilityDirection
- 7 = availability
+ 6 = all day event
+ 7 = availabilityList
+ 8 = calendarList
*/
for(CalendarReceiver.CalendarEvent event : calendarEvents)
@@ -641,7 +642,7 @@ public class Trigger
if(isActive != event.isCurrentlyActive())
{
Miscellaneous.logEvent("i", "CalendarCheck", "Event has to be currently active: " + String.valueOf(triggerParameter) + ", but is required otherwise.", 5);
- break;
+ continue;
}
if(!StringUtils.isEmpty(conditions[1]))
@@ -649,7 +650,7 @@ public class Trigger
if (!Miscellaneous.compare(conditions[0], conditions[1], event.title))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Title does not match.", 5);
- break;
+ continue;
}
}
@@ -658,7 +659,7 @@ public class Trigger
if (!Miscellaneous.compare(conditions[2], conditions[3], event.description))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Description does not match.", 5);
- break;
+ continue;
}
}
@@ -667,27 +668,39 @@ public class Trigger
if (!Miscellaneous.compare(conditions[4], conditions[5], event.location))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Location does not match.", 5);
- break;
+ continue;
}
}
- String[] availabilities = conditions[6].split(ActivityManageTriggerCalendar.separator);
- if(availabilities.length > 0)
+ if (Boolean.parseBoolean(conditions[6]) != event.allDay)
{
- if(!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
+ Miscellaneous.logEvent("i", "CalendarCheck", "All day setting does not match.", 5);
+ continue;
+ }
+
+ if(!StringUtils.isEmpty(conditions[7]))
+ {
+ String[] availabilities = conditions[7].split(ActivityManageTriggerCalendar.separator);
+ if (availabilities.length > 0)
{
- Miscellaneous.logEvent("i", "CalendarCheck", "Availability does not match.", 5);
- break;
+ if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
+ {
+ Miscellaneous.logEvent("i", "CalendarCheck", "Availability does not match.", 5);
+ continue;
+ }
}
}
- String[] calendars = conditions[7].split(ActivityManageTriggerCalendar.separator);
- if(availabilities.length > 0)
+ if(!StringUtils.isEmpty(conditions[8]))
{
- if(!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
+ String[] calendars = conditions[8].split(ActivityManageTriggerCalendar.separator);
+ if (calendars.length > 0)
{
- Miscellaneous.logEvent("i", "CalendarCheck", "Calendar does not match.", 5);
- break;
+ if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
+ {
+ Miscellaneous.logEvent("i", "CalendarCheck", "Calendar does not match.", 5);
+ continue;
+ }
}
}
@@ -696,9 +709,16 @@ public class Trigger
return true;
}
- //At this point none of the calendar items matches this trigger
+ // At this point none of the calendar items matches this trigger
- //TODO: If trigger demands no calendar event and there is absolutely no future event, we'll need to check for that.
+ // If trigger demands no calendar event and there is absolutely no future event, we'll need to check for that.
+ if(calendarEvents.size() == 0)
+ {
+ if(getTriggerParameter() == false)
+ return true;
+
+ // Further criteria don't matter if there are no events to check
+ }
}
catch(Exception e)
{
@@ -1927,9 +1947,9 @@ public class Trigger
||
!StringUtils.isEmpty(conditions[5])
||
- !StringUtils.isEmpty(conditions[6])
+ !StringUtils.isEmpty(conditions[7])
||
- !StringUtils.isEmpty(conditions[7]))
+ !StringUtils.isEmpty(conditions[8]))
{
returnString.append(" (");
@@ -1940,11 +1960,16 @@ public class Trigger
if (!StringUtils.isEmpty(conditions[5]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendarDescription) + " " + conditions[4] + " " + conditions[5] + ", ");
- if (!StringUtils.isEmpty(conditions[6]))
- returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[6] + ", ");
+ if(Boolean.parseBoolean(conditions[6]))
+ returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventTrue) + ", ");
+ else
+ returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventFalse) + ", ");
if (!StringUtils.isEmpty(conditions[7]))
- returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[7]);
+ returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[7] + ", ");
+
+ if (!StringUtils.isEmpty(conditions[8]))
+ returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[8]);
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 f0e047b6..1ad92d05 100644
--- a/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java
+++ b/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java
@@ -30,6 +30,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
public static final int AVAILABILITY_WORKING_ELSEWHERE = 5;
static List calendarsCache = null;
+ static List calendarEventsCache = null;
public static CalendarReceiver getInstance()
{
@@ -44,6 +45,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_PROVIDER_CHANGED))
{
+ calendarsCache = null;
+ calendarEventsCache = null;
+
ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
for(int i = 0; i < ruleCandidates.size(); i++)
{
@@ -65,6 +69,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{
calendarIntentFilter = new IntentFilter();
calendarIntentFilter.addAction(Intent.ACTION_PROVIDER_CHANGED);
+// calendarIntentFilter.addDataScheme("content");
}
AutomationService.getInstance().registerReceiver(calendarReceiverInstance, calendarIntentFilter);
@@ -104,6 +109,14 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{
public int calendarId;
public String displayName;
+ public String accountString;
+
+ @NonNull
+ @Override
+ public String toString()
+ {
+ return displayName + " (" + accountString + ")";
+ }
}
public static class CalendarEvent
@@ -142,7 +155,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
cursor = context.getContentResolver().query(
Uri.parse("content://com.android.calendar/calendars"),
- new String[]{"_id", "calendar_displayName"},
+ new String[]{ "_id", "calendar_displayName", "ownerAccount", },
null, null, null);
cursor.moveToFirst();
@@ -158,6 +171,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
AndroidCalendar calendar = new AndroidCalendar();
calendar.calendarId = Integer.parseInt(cursor.getString(0));
calendar.displayName = cursor.getString(1);
+ calendar.accountString = cursor.getString(2);
calendarsCache.add(calendar);
}
@@ -176,58 +190,61 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
public static List readCalendarEvents(Context context, boolean includePastEvents)
{
- Cursor cursor;
-
- cursor = context.getContentResolver().query(
- Uri.parse("content://com.android.calendar/events"),
- new String[] { "calendar_id", "_id", "title", "description", "allDay", "dtstart", "dtend", "eventLocation", "availability" },
- null, null, null);
-
- cursor.moveToFirst();
- // fetching calendars name
- String CNames[] = new String[cursor.getCount()];
-
- List eventlist = new ArrayList<>();
-
- Calendar now = Calendar.getInstance();
-
- for (int i = 0; i < CNames.length; i++)
+ if(calendarEventsCache == null)
{
- try
+ calendarEventsCache = new ArrayList<>();
+
+ Cursor cursor;
+
+ cursor = context.getContentResolver().query(
+ Uri.parse("content://com.android.calendar/events"),
+ new String[] { "calendar_id", "_id", "title", "description", "allDay", "dtstart", "dtend", "eventLocation", "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++)
{
- CalendarEvent event = new CalendarEvent();
- event.calendarId = Integer.parseInt(cursor.getString(0));
-
- for(AndroidCalendar cal : readCalendars(context))
+ try
{
- if(cal.calendarId == event.calendarId)
+ CalendarEvent event = new CalendarEvent();
+ event.calendarId = Integer.parseInt(cursor.getString(0));
+
+ for(AndroidCalendar cal : readCalendars(context))
{
- event.calendar = cal;
- break;
+ 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);
+
+ if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis())
+ calendarEventsCache.add(event);
}
-
- 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);
-
- if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis())
- eventlist.add(event);
+ catch (Exception e)
+ {}
+ cursor.moveToNext();
}
- catch (Exception e)
- {}
- cursor.moveToNext();
+
+ if(cursor != null)
+ cursor.close();
}
- if(cursor != null)
- cursor.close();
-
- return eventlist;
+ return calendarEventsCache;
}
public static void startCalendarReceiver(final AutomationService automationServiceRef)
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 4890bfd5..4731b46c 100644
--- a/app/src/main/res/layout/activity_manage_trigger_calendar.xml
+++ b/app/src/main/res/layout/activity_manage_trigger_calendar.xml
@@ -168,6 +168,30 @@
+
+
+
+
+
+
+
+
+
+
any calender
availabilities
In this trigger calendars with IDs %1$s have been previously configured, but have been deleted since. With the next save those will be removed from this trigger. Until then this trigger/condition will never be met.
+ account
+ All day event
+ event is an all day event
+ event is not an all day event
\ No newline at end of file