calendar trigger
This commit is contained in:
parent
c61c5ba14c
commit
58ec35aae5
@ -51,6 +51,9 @@ public class ActivityManageTriggerCalendar extends Activity
|
|||||||
Miscellaneous.setDisplayLanguage(this);
|
Miscellaneous.setDisplayLanguage(this);
|
||||||
setContentView(R.layout.activity_manage_trigger_calendar);
|
setContentView(R.layout.activity_manage_trigger_calendar);
|
||||||
|
|
||||||
|
// TODO: calculateNextWakeup() muß neu ausgeführt werden, wenn die Regeln geändert werden.
|
||||||
|
|
||||||
|
|
||||||
chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive);
|
chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive);
|
||||||
spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection);
|
spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection);
|
||||||
spinnerCalendarLocationDirection = (Spinner)findViewById(R.id.spinnerCalendarLocationDirection);
|
spinnerCalendarLocationDirection = (Spinner)findViewById(R.id.spinnerCalendarLocationDirection);
|
||||||
|
@ -257,7 +257,7 @@ public class Trigger
|
|||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
case calendarEvent:
|
case calendarEvent:
|
||||||
if(!checkCalendarEvent())
|
if(!checkCalendarEvent(false))
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -617,7 +617,7 @@ public class Trigger
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkCalendarEvent()
|
public boolean checkCalendarEvent(boolean ignoreActive)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -638,71 +638,8 @@ public class Trigger
|
|||||||
|
|
||||||
for(CalendarReceiver.CalendarEvent event : calendarEvents)
|
for(CalendarReceiver.CalendarEvent event : calendarEvents)
|
||||||
{
|
{
|
||||||
boolean isActive = getTriggerParameter();
|
if(!checkCalendarEvent(event, ignoreActive))
|
||||||
if(isActive != event.isCurrentlyActive())
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Event has to be currently active: " + String.valueOf(triggerParameter) + ", but is required otherwise.", 5);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(conditions[1]))
|
|
||||||
{
|
|
||||||
if (!Miscellaneous.compare(conditions[0], conditions[1], event.title))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Title does not match.", 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(conditions[3]))
|
|
||||||
{
|
|
||||||
if (!Miscellaneous.compare(conditions[2], conditions[3], event.description))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Description does not match.", 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(conditions[5]))
|
|
||||||
{
|
|
||||||
if (!Miscellaneous.compare(conditions[4], conditions[5], event.location))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Location does not match.", 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Boolean.parseBoolean(conditions[6]) != event.allDay)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Availability does not match.", 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(conditions[8]))
|
|
||||||
{
|
|
||||||
String[] calendars = conditions[8].split(ActivityManageTriggerCalendar.separator);
|
|
||||||
if (calendars.length > 0)
|
|
||||||
{
|
|
||||||
if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Calendar does not match.", 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No contradictions found
|
// No contradictions found
|
||||||
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
|
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
|
||||||
@ -728,6 +665,95 @@ public class Trigger
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean checkCalendarEvent(CalendarReceiver.CalendarEvent event, boolean ignoreActive)
|
||||||
|
{
|
||||||
|
String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
||||||
|
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 = titleDirection
|
||||||
|
1 = title;
|
||||||
|
2 = descriptionDirection
|
||||||
|
3 = description
|
||||||
|
4 = eventLocationDirection
|
||||||
|
5 = eventLocation
|
||||||
|
6 = all day event
|
||||||
|
7 = availabilityList
|
||||||
|
8 = calendarList
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
boolean isActive = getTriggerParameter();
|
||||||
|
if (!ignoreActive && isActive != event.isCurrentlyActive())
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Event has to be currently active: " + String.valueOf(triggerParameter) + ", but is required otherwise.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(conditions[1]))
|
||||||
|
{
|
||||||
|
if (!Miscellaneous.compare(conditions[0], conditions[1], event.title))
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Title does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(conditions[3]))
|
||||||
|
{
|
||||||
|
if (!Miscellaneous.compare(conditions[2], conditions[3], event.description))
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Description does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(conditions[5]))
|
||||||
|
{
|
||||||
|
if (!Miscellaneous.compare(conditions[4], conditions[5], event.location))
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Location does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.parseBoolean(conditions[6]) != event.allDay)
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "All day setting does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(conditions[7]))
|
||||||
|
{
|
||||||
|
String[] availabilities = conditions[7].split(ActivityManageTriggerCalendar.separator);
|
||||||
|
if (availabilities.length > 0)
|
||||||
|
{
|
||||||
|
if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Availability does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(conditions[8]))
|
||||||
|
{
|
||||||
|
String[] calendars = conditions[8].split(ActivityManageTriggerCalendar.separator);
|
||||||
|
if (calendars.length > 0)
|
||||||
|
{
|
||||||
|
if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Calendar does not match.", 5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO: all-day abwählbar machen
|
||||||
|
// No contradictions found
|
||||||
|
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
boolean checkBluetooth()
|
boolean checkBluetooth()
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Checking for bluetooth...", this.getParentRule().getName()), 4);
|
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Checking for bluetooth...", this.getParentRule().getName()), 4);
|
||||||
|
@ -9,7 +9,6 @@ import android.content.IntentFilter;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.SystemClock;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@ -20,6 +19,7 @@ import com.jens.automation2.Trigger;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
@ -43,7 +43,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
|
|||||||
static TimerTask timerTask = null;
|
static TimerTask timerTask = null;
|
||||||
static Calendar nextWakeup = null;
|
static Calendar nextWakeup = null;
|
||||||
static AlarmManager alarmManager = null;
|
static AlarmManager alarmManager = null;
|
||||||
static boolean alarmHasChanged = false;
|
static boolean wakeupNeedsToBeScheduled = false;
|
||||||
|
|
||||||
public static CalendarReceiver getInstance()
|
public static CalendarReceiver getInstance()
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
|
|||||||
}
|
}
|
||||||
else if(intent.getAction().equalsIgnoreCase(calendarAlarmAction))
|
else if(intent.getAction().equalsIgnoreCase(calendarAlarmAction))
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "AlarmReceiver", "Received alarm for calendar receiver.", 5);
|
Miscellaneous.logEvent("i", "CalendarReceiver", "Received alarm for calendar receiver.", 5);
|
||||||
routineAtAlarm();
|
routineAtAlarm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If it's now filled, go on
|
// If it's now filled, go on
|
||||||
if(nextWakeup != null)
|
if(nextWakeup != null && wakeupNeedsToBeScheduled)
|
||||||
{
|
{
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||||
{
|
{
|
||||||
@ -340,10 +340,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
Miscellaneous.logEvent("i", "armOrRearmTimer()", "Setting calendar alarm for " + nextWakeup.toString(), 5);
|
Miscellaneous.logEvent("i", "armOrRearmTimer()", "Scheduling wakeup for calendar at " + Miscellaneous.formatDate(nextWakeup.getTime()), 5);
|
||||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextWakeup.getTimeInMillis(), pi);
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextWakeup.getTimeInMillis(), pi);
|
||||||
|
wakeupNeedsToBeScheduled = false;
|
||||||
//alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextWakeup.getTimeInMillis(), pi);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -354,38 +353,58 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
|
|||||||
private static void calculateNextWakeup()
|
private static void calculateNextWakeup()
|
||||||
{
|
{
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
if (nextWakeup != null && nextWakeup.getTimeInMillis() < now.getTimeInMillis())
|
|
||||||
nextWakeup = null;
|
|
||||||
|
|
||||||
List<CalendarEvent> events = readCalendarEvents(Miscellaneous.getAnyContext(), false);
|
List<CalendarEvent> events = readCalendarEvents(Miscellaneous.getAnyContext(), false);
|
||||||
if (events.size() > 0)
|
|
||||||
|
if (events.size() == 0)
|
||||||
{
|
{
|
||||||
for (CalendarEvent event : events)
|
Miscellaneous.logEvent("i", "calculateNextWakeup()", "No future events, nothing to schedule.", 5);
|
||||||
{
|
|
||||||
if (event.isCurrentlyActive())
|
|
||||||
{
|
|
||||||
if (nextWakeup == null || event.end.getTimeInMillis() < nextWakeup.getTimeInMillis())
|
|
||||||
{
|
|
||||||
nextWakeup = event.end;
|
|
||||||
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose end of event " + event.title + " as next wakeup.", 5);
|
|
||||||
if(!alarmHasChanged)
|
|
||||||
alarmHasChanged = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (nextWakeup == null || event.start.getTimeInMillis() < nextWakeup.getTimeInMillis())
|
List<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
|
||||||
|
List<Long> wakeUpCandidatesList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (CalendarEvent event : events)
|
||||||
{
|
{
|
||||||
nextWakeup = event.start;
|
for (Rule r : ruleCandidates)
|
||||||
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose start of event " + event.title + " as next wakeup.", 5);
|
{
|
||||||
if(!alarmHasChanged)
|
for (Trigger t : r.getTriggerSet())
|
||||||
alarmHasChanged = true;
|
{
|
||||||
|
if (t.getTriggerType().equals(Trigger.Trigger_Enum.calendarEvent) && t.checkCalendarEvent(event, true))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Device needs to wakeup at start AND end of events, no matter what is specified in triggers.
|
||||||
|
This is because we also need to know when a trigger doesn't apply anymore to make it
|
||||||
|
count for hasStateNotAppliedSinceLastRuleExecution().
|
||||||
|
Otherwise the same rule would not get executed again even after calendar events have come and gone.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(event.start.getTimeInMillis() > now.getTimeInMillis())
|
||||||
|
wakeUpCandidatesList.add(event.start.getTimeInMillis());
|
||||||
|
|
||||||
|
if(event.end.getTimeInMillis() > now.getTimeInMillis())
|
||||||
|
wakeUpCandidatesList.add(event.end.getTimeInMillis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
// we expect to be called byOnReceive() when new items exist
|
Collections.sort(wakeUpCandidatesList);
|
||||||
|
|
||||||
|
if(nextWakeup == null || nextWakeup.getTimeInMillis() != wakeUpCandidatesList.get(0))
|
||||||
|
{
|
||||||
|
Calendar newAlarm = Miscellaneous.calendarFromLong(wakeUpCandidatesList.get(0));
|
||||||
|
if(nextWakeup == null)
|
||||||
|
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was null.", 5);
|
||||||
|
else
|
||||||
|
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was " + Miscellaneous.formatDate(nextWakeup.getTime()), 5);
|
||||||
|
nextWakeup = newAlarm;
|
||||||
|
if (!wakeupNeedsToBeScheduled)
|
||||||
|
wakeupNeedsToBeScheduled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Alarm " + Miscellaneous.formatDate(nextWakeup.getTime()) + " has been selected as next wakeup, but not rescheduling since this was not a change.", 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startCalendarReceiver(final AutomationService automationServiceRef)
|
public static void startCalendarReceiver(final AutomationService automationServiceRef)
|
||||||
|
@ -175,6 +175,13 @@
|
|||||||
android:layout_marginVertical="@dimen/default_margin"
|
android:layout_marginVertical="@dimen/default_margin"
|
||||||
android:background="#aa000000" />
|
android:background="#aa000000" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/careAboutAllDayEvent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/evaluate"
|
||||||
|
android:checked="true"/>
|
||||||
|
|
||||||
<TableRow
|
<TableRow
|
||||||
android:layout_marginBottom="@dimen/activity_vertical_margin">
|
android:layout_marginBottom="@dimen/activity_vertical_margin">
|
||||||
|
|
||||||
|
@ -933,4 +933,5 @@
|
|||||||
<string name="errorReadingCalendars">There was an error reading the calendars on your device.</string>
|
<string name="errorReadingCalendars">There was an error reading the calendars on your device.</string>
|
||||||
<string name="android.permission.SCHEDULE_EXACT_ALARM">Schedule exact alarms</string>
|
<string name="android.permission.SCHEDULE_EXACT_ALARM">Schedule exact alarms</string>
|
||||||
<string name="alarmsPermissionHint">After clicking OK a window will open. Please select Automation there and allow the app to schedule exact alarms.</string>
|
<string name="alarmsPermissionHint">After clicking OK a window will open. Please select Automation there and allow the app to schedule exact alarms.</string>
|
||||||
|
<string name="evaluate">Evaluate</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user