New version prep, fix attempt in notification listener

This commit is contained in:
Jens 2024-02-07 23:24:03 +01:00
parent 500610fb98
commit 31d167a93f
2 changed files with 99 additions and 50 deletions

View File

@ -1447,9 +1447,18 @@ public class Trigger
*/ */
Calendar timeSupposedToRunNext = getNextRepeatedExecutionAfter(this, lastExec); Calendar timeSupposedToRunNext = getNextRepeatedExecutionAfter(this, lastExec);
if(now.getTimeInMillis() > timeSupposedToRunNext.getTimeInMillis())
return true;
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Last execution: " + Miscellaneous.formatDate(lastExec.getTime()), 5);
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Next execution: " + Miscellaneous.formatDate(timeSupposedToRunNext.getTime()), 5);
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Now: " + Miscellaneous.formatDate(now.getTime()), 5);
if(now.getTimeInMillis() > timeSupposedToRunNext.getTimeInMillis())
{
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Repetition due.", 5);
return true;
}
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Repetition not due.", 5);
return false; return false;
} }

View File

@ -23,20 +23,19 @@ import java.sql.Time;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
public class DateTimeListener extends BroadcastReceiver implements AutomationListenerInterface public class DateTimeListener extends BroadcastReceiver implements AutomationListenerInterface
{ {
private static AutomationService automationServiceRef; private static AutomationService automationServiceRef;
private static AlarmManager centralAlarmManagerInstance; private static AlarmManager centralAlarmManagerInstance;
private static boolean alarmListenerActive = false; private static boolean alarmListenerActive=false;
private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>(); private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>();
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>(); private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
static PendingIntent alarmPendingIntent = null; static PendingIntent alarmPendingIntent = null;
public static void startAlarmListener(final AutomationService automationServiceRef) public static void startAlarmListener(final AutomationService automationServiceRef)
{ {
DateTimeListener.startAlarmListenerInternal(automationServiceRef); DateTimeListener.startAlarmListenerInternal(automationServiceRef);
} }
public static void stopAlarmListener(Context context) public static void stopAlarmListener(Context context)
@ -48,7 +47,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
{ {
return alarmListenerActive; return alarmListenerActive;
} }
@Override @Override
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
@ -60,10 +59,10 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context)) if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context))
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false); allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
} }
setAlarms(); setAlarms();
} }
@RequiresApi(api = Build.VERSION_CODES.KITKAT) @RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static void setAlarms() public static void setAlarms()
{ {
@ -71,11 +70,11 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
Calendar calNow = Calendar.getInstance(); Calendar calNow = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm"); SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
clearAlarms(); clearAlarms();
int i=0; int i=0;
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>(); ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame); allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
// allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame(); // allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame();
@ -192,8 +191,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
* 4. Take div result +1 and add this on top of starting time * 4. Take div result +1 and add this on top of starting time
* 5. Is this next possible execution still inside timeframe? Also consider timeframes spanning over midnight * 5. Is this next possible execution still inside timeframe? Also consider timeframes spanning over midnight
*/ */
Calendar calSet;
Time setTime;
TimeFrame tf = new TimeFrame(oneTrigger.getTriggerParameter2()); TimeFrame tf = new TimeFrame(oneTrigger.getTriggerParameter2());
if(tf.getRepetition() > 0) if(tf.getRepetition() > 0)
@ -202,7 +200,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
{ {
Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow); Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow);
alarmCandidates.add(new ScheduleElement(calSchedule, "Rule " + oneRule.getName() + ", repetition in trigger " + oneTrigger.toString())); alarmCandidates.add(new ScheduleElement(calSchedule, "Rule " + oneRule.getName() + ", trigger " + oneTrigger.toString()));
} }
} }
} }
@ -214,36 +212,51 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
} }
} }
} }
scheduleNextAlarm(); scheduleNextAlarm();
} }
private static void scheduleNextAlarm() private static void scheduleNextAlarm()
{ {
Long currentTime = System.currentTimeMillis();
ScheduleElement scheduleCandidate = null;
if(alarmCandidates.size() == 0) if(alarmCandidates.size() == 0)
{ {
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3); Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
return;
} }
else else if(alarmCandidates.size() == 1)
{ {
Collections.sort(alarmCandidates); // only one alarm, schedule that
scheduleCandidate = alarmCandidates.get(0);
Miscellaneous.logEvent("i", "AlarmManager", "Chose this as next scheduled alarm: " + alarmCandidates.get(0), 4);
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
else
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
centralAlarmManagerInstance.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmCandidates.get(0).time.getTimeInMillis(), alarmPendingIntent);
else
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, alarmCandidates.get(0).time.getTimeInMillis(), alarmPendingIntent);
} }
else if(alarmCandidates.size() > 1)
{
scheduleCandidate = alarmCandidates.get(0);
for(ScheduleElement alarmCandidate : alarmCandidates)
{
if(Math.abs(currentTime - alarmCandidate.time.getTimeInMillis()) < Math.abs(currentTime - scheduleCandidate.time.getTimeInMillis()))
scheduleCandidate = alarmCandidate;
}
}
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
else
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm:ss");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(scheduleCandidate.time.getTimeInMillis());
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
} }
public static void clearAlarms() public static void clearAlarms()
{ {
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4); Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
@ -252,12 +265,12 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class); Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
if(alarmPendingIntent == null) if(alarmPendingIntent == null)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0); alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
// Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode));
centralAlarmManagerInstance.cancel(alarmPendingIntent); centralAlarmManagerInstance.cancel(alarmPendingIntent);
} }
requestCodeList.clear(); requestCodeList.clear();
} }
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef) private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
{ {
if(!alarmListenerActive) if(!alarmListenerActive)
@ -265,20 +278,29 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4); Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
DateTimeListener.automationServiceRef = givenAutomationServiceRef; DateTimeListener.automationServiceRef = givenAutomationServiceRef;
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE); centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
// alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
// alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, 0);
alarmListenerActive = true; alarmListenerActive = true;
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4); Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
DateTimeListener.setAlarms(); DateTimeListener.setAlarms();
// // get a Calendar object with current time
// Calendar cal = Calendar.getInstance();
// // add 5 minutes to the calendar object
// cal.add(Calendar.SECOND, 10);
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent);
} }
else else
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5); Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
} }
private static void stopAlarmListenerInternal() private static void stopAlarmListenerInternal()
{ {
if(alarmListenerActive) if(alarmListenerActive)
{ {
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4); Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
clearAlarms(); clearAlarms();
centralAlarmManagerInstance.cancel(alarmPendingIntent);
alarmListenerActive = false; alarmListenerActive = false;
} }
else else
@ -348,37 +370,55 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
@RequiresApi(api = Build.VERSION_CODES.N) @RequiresApi(api = Build.VERSION_CODES.N)
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now) public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
{ {
Calendar calSet; Calendar calculationStart;
TimeObject setTime; TimeObject setTime;
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2()); TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
if(tf.getRepetition() > 0) if(tf.getRepetition() > 0)
{ {
if(trigger.getTriggerParameter()) if(trigger.getParentRule().getLastExecution() != null)
setTime = tf.getTriggerTimeStart(); {
Miscellaneous.logEvent("i", "DateTimeListener", "Chose last runtime of rule " + trigger.getParentRule().getName() + " as calculation start.", 5);
calculationStart = trigger.getParentRule().getLastExecution();
}
else else
setTime = tf.getTriggerTimeStop(); {
if(trigger.getTriggerParameter())
{
Miscellaneous.logEvent("i", "DateTimeListener", "Chose start of next interval of trigger in rule " + trigger.getParentRule().getName() + " as calculation start.", 5);
setTime = tf.getTriggerTimeStart();
}
else
{
Miscellaneous.logEvent("i", "DateTimeListener", "Chose end of next interval of trigger in rule " + trigger.getParentRule().getName() + " as calculation start.", 5);
setTime = tf.getTriggerTimeStop();
}
calSet = (Calendar) now.clone(); calculationStart = (Calendar) now.clone();
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours()); calculationStart.set(Calendar.HOUR_OF_DAY, setTime.getHours());
calSet.set(Calendar.MINUTE, setTime.getMinutes()); calculationStart.set(Calendar.MINUTE, setTime.getMinutes());
calSet.set(Calendar.SECOND, 0); calculationStart.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0); // calculationStart.set(Calendar.MILLISECOND, 0);
}
// If the starting time is a day ahead remove 1 day. // If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis()) if(calculationStart.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1); calculationStart.add(Calendar.DAY_OF_MONTH, -1);
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calSet.getTimeInMillis()) / 1000; Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calculationStart.getTime()) + " as calculation start.", 5);
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1; long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
long nextScheduleTimestamp = (calSet.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition()); long nextScheduleTimestamp = (calculationStart.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition());
Calendar calSchedule = Calendar.getInstance(); Calendar calSchedule = Calendar.getInstance();
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000); calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
return calSchedule; return calSchedule;
} }
else else
Miscellaneous.logEvent("i", "DateTimeListener", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5); Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
return null; return null;
} }