forked from jens/Automation
302 lines
12 KiB
Java
302 lines
12 KiB
Java
package com.jens.automation2.receivers;
|
|
|
|
import android.app.AlarmManager;
|
|
import android.app.PendingIntent;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
|
|
import com.jens.automation2.AutomationService;
|
|
import com.jens.automation2.Miscellaneous;
|
|
import com.jens.automation2.Rule;
|
|
import com.jens.automation2.Trigger;
|
|
import com.jens.automation2.Trigger.Trigger_Enum;
|
|
|
|
import java.sql.Time;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
|
|
public class AlarmListener extends BroadcastReceiver implements AutomationListenerInterface
|
|
{
|
|
private static AutomationService automationServiceRef;
|
|
private static AlarmManager centralAlarmManagerInstance;
|
|
// private static Intent alarmIntent;
|
|
// private static PendingIntent alarmPendingIntent;
|
|
private static boolean alarmListenerActive=false;
|
|
private static ArrayList<Long> alarmCandidates = new ArrayList<Long>();
|
|
|
|
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
|
|
|
|
public static void startAlarmListener(final AutomationService automationServiceRef)
|
|
{
|
|
AlarmListener.startAlarmListenerInternal(automationServiceRef);
|
|
}
|
|
public static void stopAlarmListener(Context context)
|
|
{
|
|
AlarmListener.stopAlarmListenerInternal();
|
|
}
|
|
|
|
public static boolean isAlarmListenerActive()
|
|
{
|
|
return alarmListenerActive;
|
|
}
|
|
|
|
@Override
|
|
public void onReceive(Context context, Intent intent)
|
|
{
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
|
|
Date now = new Date();
|
|
String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds());
|
|
Time passTime = Time.valueOf(timeString);
|
|
|
|
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime);
|
|
for(int i=0; i<allRulesWithNowInTimeFrame.size(); i++)
|
|
{
|
|
if(allRulesWithNowInTimeFrame.get(i).applies(context))
|
|
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
|
|
}
|
|
|
|
setAlarms();
|
|
}
|
|
|
|
public static void setAlarms()
|
|
{
|
|
alarmCandidates.clear();
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
|
|
|
clearAlarms();
|
|
|
|
int i=0;
|
|
|
|
// // get a Calendar object with current time
|
|
// Calendar cal = Calendar.getInstance();
|
|
// // add 5 minutes to the calendar object
|
|
// cal.add(Calendar.SECOND, 10);
|
|
// String calSetWorkingCopyString2 = null;
|
|
// SimpleDateFormat sdf2 = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
|
// if (cal != null)
|
|
// {
|
|
// calSetWorkingCopyString2 = sdf2.format(cal.getTime());
|
|
// }
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of hardcoded test: beginning at " + calSetWorkingCopyString2);
|
|
// Intent alarmIntent2 = new Intent(automationServiceRef, AlarmListener.class);
|
|
// PendingIntent alarmPendingIntent2 = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent2, 0);
|
|
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent2);
|
|
// requestCodeList.add(0);
|
|
|
|
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
|
|
allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame();
|
|
for(Rule oneRule : allRulesWithTimeFrames)
|
|
{
|
|
for(Trigger oneTrigger : oneRule.getTriggerSet())
|
|
{
|
|
if(oneTrigger.getTriggerType() == Trigger_Enum.timeFrame)
|
|
{
|
|
Calendar calNow, calSet;
|
|
Time setTime;
|
|
|
|
if(oneTrigger.getTriggerParameter())
|
|
setTime = oneTrigger.getTimeFrame().getTriggerTimeStart();
|
|
else
|
|
setTime = oneTrigger.getTimeFrame().getTriggerTimeStop();
|
|
|
|
calNow = Calendar.getInstance();
|
|
calSet = (Calendar) calNow.clone();
|
|
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
|
calSet.set(Calendar.MINUTE, setTime.getMinutes());
|
|
calSet.set(Calendar.SECOND, 0);
|
|
calSet.set(Calendar.MILLISECOND, 0);
|
|
// At this point calSet would be a scheduling candidate. It's just the day the might not be right, yet.
|
|
|
|
long milliSecondsInAWeek = 1000 * 60 * 60 * 24 * 7;
|
|
|
|
for(int dayOfWeek : oneTrigger.getTimeFrame().getDayList())
|
|
{
|
|
Calendar calSetWorkingCopy = (Calendar) calSet.clone();
|
|
|
|
// calSetWorkingCopy.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
|
// calSetWorkingCopy.set(Calendar.MINUTE, setTime.getMinutes());
|
|
// calSetWorkingCopy.set(Calendar.SECOND, 0);
|
|
// calSetWorkingCopy.set(Calendar.MILLISECOND, 0);
|
|
|
|
int diff = dayOfWeek - calNow.get(Calendar.DAY_OF_WEEK);
|
|
// Log.i("AlarmManager", "Today: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + " / Sched.Day: " + String.valueOf(dayOfWeek) + " Difference to target day is: " + String.valueOf(diff));
|
|
if(diff == 0) //if we're talking about the current day, is the time still in the future?
|
|
{
|
|
if(calSetWorkingCopy.getTime().getHours() < calNow.getTime().getHours())
|
|
{
|
|
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getHours(" + String.valueOf(calSetWorkingCopy.getTime().getHours()) + ") < calNow.getTime().getHours(" + String.valueOf(calNow.getTime().getHours()) + ")");
|
|
calSetWorkingCopy.add(Calendar.DAY_OF_MONTH, 7); //add a week
|
|
}
|
|
else if(calSetWorkingCopy.getTime().getHours() == calNow.getTime().getHours())
|
|
{
|
|
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getHours() == calNow.getTime().getHours()");
|
|
if(calSetWorkingCopy.getTime().getMinutes() <= calNow.getTime().getMinutes())
|
|
{
|
|
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getMinutes() < calNow.getTime().getMinutes()");
|
|
calSetWorkingCopy.add(Calendar.DAY_OF_MONTH, 7); //add a week
|
|
}
|
|
}
|
|
}
|
|
else if(diff < 0)
|
|
{
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Adding " + String.valueOf(diff+7) + " on top of " + String.valueOf(calSetWorkingCopy.get(Calendar.DAY_OF_WEEK)));
|
|
calSetWorkingCopy.add(Calendar.DAY_OF_WEEK, diff+7); // it's a past weekday, schedule for next week
|
|
}
|
|
else
|
|
{
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Adding " + String.valueOf(diff) + " on top of " + String.valueOf(calSetWorkingCopy.get(Calendar.DAY_OF_WEEK)));
|
|
calSetWorkingCopy.add(Calendar.DAY_OF_WEEK, diff); // it's a future weekday, schedule for that day
|
|
}
|
|
|
|
i++;
|
|
i=(int)System.currentTimeMillis();
|
|
String calSetWorkingCopyString = sdf.format(calSetWorkingCopy.getTime()) + " RequestCode: " + String.valueOf(i);
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of rule: " + oneRule.getName() + " beginning at " + calSetWorkingCopyString);
|
|
|
|
alarmCandidates.add(calSetWorkingCopy.getTimeInMillis());
|
|
// Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
|
// alarmIntent.setData(Uri.parse("myalarms://" + i));
|
|
// PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, i, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, calSetWorkingCopy.getTimeInMillis(), milliSecondsInAWeek, alarmPendingIntent);
|
|
// requestCodeList.add(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// // get a Calendar object with current time
|
|
// Calendar cal = Calendar.getInstance();
|
|
// cal.add(Calendar.SECOND, 10);
|
|
// String calSetWorkingCopyString2 = sdf.format(cal.getTime());
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of hardcoded test: beginning at " + calSetWorkingCopyString2);
|
|
// Intent alarmIntent2 = new Intent(automationServiceRef, AlarmListener.class);
|
|
// PendingIntent alarmPendingIntent2 = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent2, 0);
|
|
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent2);
|
|
// requestCodeList.add(0);
|
|
|
|
scheduleNextAlarm();
|
|
}
|
|
|
|
private static void scheduleNextAlarm()
|
|
{
|
|
Long currentTime = System.currentTimeMillis();
|
|
Long scheduleCandidate = null;
|
|
|
|
if(alarmCandidates.size() == 0)
|
|
{
|
|
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
|
|
return;
|
|
}
|
|
else if(alarmCandidates.size() == 1)
|
|
{
|
|
// only one alarm, schedule that
|
|
scheduleCandidate = alarmCandidates.get(0);
|
|
}
|
|
else if(alarmCandidates.size() > 1)
|
|
{
|
|
scheduleCandidate = alarmCandidates.get(0);
|
|
|
|
for(long alarmCandidate : alarmCandidates)
|
|
{
|
|
if(Math.abs(currentTime - alarmCandidate) < Math.abs(currentTime - scheduleCandidate))
|
|
scheduleCandidate = alarmCandidate;
|
|
}
|
|
}
|
|
|
|
Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
|
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate, alarmPendingIntent);
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
|
Calendar calendar = Calendar.getInstance();
|
|
calendar.setTimeInMillis(scheduleCandidate);
|
|
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
|
|
|
|
}
|
|
|
|
public static void clearAlarms()
|
|
{
|
|
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
|
|
for(int requestCode : requestCodeList)
|
|
{
|
|
Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
|
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
|
|
// Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode));
|
|
centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
|
}
|
|
requestCodeList.clear();
|
|
}
|
|
|
|
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
|
|
{
|
|
if(!alarmListenerActive)
|
|
{
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
|
|
AlarmListener.automationServiceRef = givenAutomationServiceRef;
|
|
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
|
|
// alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
|
// alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, 0);
|
|
alarmListenerActive = true;
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
|
|
AlarmListener.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
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
|
|
}
|
|
|
|
private static void stopAlarmListenerInternal()
|
|
{
|
|
if(alarmListenerActive)
|
|
{
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
|
|
clearAlarms();
|
|
// centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
|
alarmListenerActive = false;
|
|
}
|
|
else
|
|
Miscellaneous.logEvent("i", "AlarmListener", "Request to stop AlarmListener. But it's not running.", 5);
|
|
}
|
|
public static void reloadAlarms()
|
|
{
|
|
AlarmListener.setAlarms();
|
|
}
|
|
@Override
|
|
public void startListener(AutomationService automationService)
|
|
{
|
|
AlarmListener.startAlarmListener(automationService);
|
|
}
|
|
@Override
|
|
public void stopListener(AutomationService automationService)
|
|
{
|
|
AlarmListener.stopAlarmListener(automationService);
|
|
}
|
|
|
|
public static boolean haveAllPermission()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isListenerRunning()
|
|
{
|
|
return isAlarmListenerActive();
|
|
}
|
|
@Override
|
|
public Trigger_Enum[] getMonitoredTrigger()
|
|
{
|
|
return new Trigger_Enum[] { Trigger_Enum.timeFrame };
|
|
}
|
|
|
|
}
|