Calendar trigger

This commit is contained in:
jens 2024-01-06 17:25:27 +01:00
parent 223cca442d
commit ec62b91449
17 changed files with 264 additions and 169 deletions

View File

@ -139,6 +139,7 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receivers.PackageReplacedReceiver" <receiver android:name=".receivers.PackageReplacedReceiver"
android:exported="true"
android:enabled="true"> android:enabled="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
@ -151,6 +152,7 @@
<receiver <receiver
android:name=".DeviceAdmin" android:name=".DeviceAdmin"
android:exported="true"
android:description="@string/app_name" android:description="@string/app_name"
android:label="@string/app_name" android:label="@string/app_name"
android:permission= "android.permission.BIND_DEVICE_ADMIN" > android:permission= "android.permission.BIND_DEVICE_ADMIN" >
@ -193,6 +195,7 @@
<activity <activity
android:name=".ActivityMainTabLayout" android:name=".ActivityMainTabLayout"
android:exported="true"
android:launchMode="singleTask"> android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -242,6 +245,7 @@
<service <service
android:name=".receivers.NotificationListener" android:name=".receivers.NotificationListener"
android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" > android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter> <intent-filter>

View File

@ -10,9 +10,12 @@ import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.Nullable;
import com.google.android.gms.location.DetectedActivity; import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.receivers.ActivityDetectionReceiver; import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BroadcastListener; import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -376,6 +379,11 @@ public class Rule implements Comparable<Rule>
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4); Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true; return true;
} }
else if(hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent) && CalendarReceiver.mayRuleStillBeActivatedForPendingCalendarEvents(this))
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies, has not flipped since its last execution, but may still be executed for other calendar events.", 4);
return true;
}
else else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4); Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
} }
@ -780,4 +788,32 @@ public class Rule implements Comparable<Rule>
return null; return null;
} }
@Override
public boolean equals(@Nullable Object obj)
{
return this.getName().equals(((Rule)obj).getName());
}
public boolean hasTriggerOfType(Trigger.Trigger_Enum queryType)
{
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(queryType))
return true;
}
return false;
}
public boolean hasActionOfType(Action.Action_Enum queryType)
{
for(Action a : getActionSet())
{
if(a.getAction().equals(queryType))
return true;
}
return false;
}
} }

View File

@ -136,6 +136,7 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receivers.PackageReplacedReceiver" <receiver android:name=".receivers.PackageReplacedReceiver"
android:exported="true"
android:enabled="true"> android:enabled="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
@ -148,6 +149,7 @@
<receiver <receiver
android:name=".DeviceAdmin" android:name=".DeviceAdmin"
android:exported="true"
android:description="@string/app_name" android:description="@string/app_name"
android:label="@string/app_name" android:label="@string/app_name"
android:permission= "android.permission.BIND_DEVICE_ADMIN" > android:permission= "android.permission.BIND_DEVICE_ADMIN" >
@ -190,6 +192,7 @@
<activity <activity
android:name=".ActivityMainTabLayout" android:name=".ActivityMainTabLayout"
android:exported="true"
android:launchMode="singleTask"> android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -239,6 +242,7 @@
<service <service
android:name=".receivers.NotificationListener" android:name=".receivers.NotificationListener"
android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" > android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter> <intent-filter>

View File

@ -344,8 +344,17 @@ public class Rule implements Comparable<Rule>
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{ {
if(oneTrigger.getTimeFrame().repetition > 0) if(oneTrigger.getTimeFrame().repetition > 0)
{
if(this.getLastExecution() != null)
{
Calendar now = Calendar.getInstance();
if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis())
return true; return true;
} }
else
return true;
}
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived)) else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{ {
return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution()); return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution());

View File

@ -172,7 +172,6 @@
<activity android:name=".ActivityManageTriggerCheckVariable" /> <activity android:name=".ActivityManageTriggerCheckVariable" />
<activity android:name=".ActivityManageActionCopyToClipboard" /> <activity android:name=".ActivityManageActionCopyToClipboard" />
<activity android:name=".ActivityManageActionLocationService" /> <activity android:name=".ActivityManageActionLocationService" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity <activity
android:name=".ActivityMainTabLayout" android:name=".ActivityMainTabLayout"
@ -222,6 +221,7 @@
<activity android:name=".ActivityVolumeTest" /> <activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity> <activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityManageTriggerNotification" /> <activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<service <service
android:name=".receivers.NotificationListener" android:name=".receivers.NotificationListener"

View File

@ -347,8 +347,17 @@ public class Rule implements Comparable<Rule>
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{ {
if(oneTrigger.getTimeFrame().repetition > 0) if(oneTrigger.getTimeFrame().repetition > 0)
{
if(this.getLastExecution() != null)
{
Calendar now = Calendar.getInstance();
if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis())
return true; return true;
} }
else
return true;
}
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived)) else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{ {
return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution()); return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution());

View File

@ -345,17 +345,34 @@ public class Action
if (this.getAction().equals(Action_Enum.triggerUrl)) if (this.getAction().equals(Action_Enum.triggerUrl))
{ {
String[] components = parameter2.split(";"); String[] components;
if(parameter2.contains(Action.actionParameter2Split))
components = parameter2.split(Action.actionParameter2Split);
else
components = parameter2.split(";");
if (components.length >= 3) if (components.length >= 3)
{ {
returnString.append(" (");
if(components.length >= 4)
returnString.append(components[3]);
else
returnString.append(ActivityManageActionTriggerUrl.methodGet);
returnString.append(")");
returnString.append(": " + components[2]); returnString.append(": " + components[2]);
if (parameter1) if (parameter1)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + "."); returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + ".");
} }
else else
{
returnString.append(" (");
returnString.append(ActivityManageActionTriggerUrl.methodGet);;
returnString.append(")");
returnString.append(": " + components[0]); returnString.append(": " + components[0]);
} }
}
else if (this.getAction().equals(Action_Enum.startOtherActivity)) else if (this.getAction().equals(Action_Enum.startOtherActivity))
{ {
returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/")); returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/"));
@ -786,7 +803,7 @@ public class Action
if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https")) if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https"))
response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method, httpParams); response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method, httpParams);
else else
response = Miscellaneous.downloadURLwithoutCertificateChecking(urlString, urlUsername, urlPassword, method, httpParams); response = Miscellaneous.downloadUrlWithoutCertificateChecking(urlString, urlUsername, urlPassword, method, httpParams);
try try
{ {

View File

@ -1,6 +1,6 @@
package com.jens.automation2; package com.jens.automation2;
import static com.jens.automation2.ActivityManageActionTriggerUrl.edit; //import static com.jens.automation2.ActivityManageActionTriggerUrl.edit;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;

View File

@ -3,6 +3,7 @@ package com.jens.automation2;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
@ -45,8 +46,8 @@ public class ActivityManageActionTriggerUrl extends Activity
public static final String methodGet = "GET"; public static final String methodGet = "GET";
public static final String methodPost = "POST"; public static final String methodPost = "POST";
public static boolean edit = false; // public static boolean edit = false;
public static Action resultingAction = null; // public static Action resultingAction = null;
@Override @Override
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
@ -95,11 +96,9 @@ public class ActivityManageActionTriggerUrl extends Activity
{ {
if(etTriggerUrl.getText().toString().length() > 0) if(etTriggerUrl.getText().toString().length() > 0)
{ {
if(resultingAction == null) Intent returnIntent = new Intent();
resultingAction = new Action();
resultingAction.setAction(Action_Enum.triggerUrl); returnIntent.putExtra(ActivityManageRule.intentNameActionParameter1, chkTriggerUrlUseAuthentication.isChecked());
resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
String username = etTriggerUrlUsername.getText().toString(); String username = etTriggerUrlUsername.getText().toString();
String password = etTriggerUrlPassword.getText().toString(); String password = etTriggerUrlPassword.getText().toString();
@ -120,15 +119,16 @@ public class ActivityManageActionTriggerUrl extends Activity
if(httpParams.length() > 0) if(httpParams.length() > 0)
httpParams = httpParams.substring(Action.actionParameters2SeparatorOuter.length()); httpParams = httpParams.substring(Action.actionParameters2SeparatorOuter.length());
ActivityManageActionTriggerUrl.resultingAction.setParameter2( returnIntent.putExtra(ActivityManageRule.intentNameActionParameter2,
username + Action.actionParameter2Split + username + Action.actionParameter2Split +
password + Action.actionParameter2Split + password + Action.actionParameter2Split +
etTriggerUrl.getText().toString().trim() + Action.actionParameter2Split + etTriggerUrl.getText().toString().trim() + Action.actionParameter2Split +
method + Action.actionParameter2Split + method + Action.actionParameter2Split +
httpParams httpParams
); );
//TODO: Check if http params listview is scrollable
backToRuleManager(); setResult(RESULT_OK, returnIntent);
finish();
} }
else else
Toast.makeText(getBaseContext(), getResources().getString(R.string.urlTooShort), Toast.LENGTH_LONG).show(); Toast.makeText(getBaseContext(), getResources().getString(R.string.urlTooShort), Toast.LENGTH_LONG).show();
@ -170,21 +170,20 @@ public class ActivityManageActionTriggerUrl extends Activity
}); });
updateListView(); updateListView();
ActivityManageActionTriggerUrl.edit = getIntent().getBooleanExtra("edit", false); if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
if(edit)
{ {
// username,password,URL,etc. // username,password,URL,etc.
String[] components; String[] components;
if(ActivityManageActionTriggerUrl.resultingAction.getParameter2().contains(Action.actionParameter2Split)) if(getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).contains(Action.actionParameter2Split))
components = ActivityManageActionTriggerUrl.resultingAction.getParameter2().split(Action.actionParameter2Split, -1); components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(Action.actionParameter2Split, -1);
else else
components = ActivityManageActionTriggerUrl.resultingAction.getParameter2().split(";", -1); components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(";", -1);
if(components.length >= 3) if(components.length >= 3)
{ {
etTriggerUrl.setText(components[2]); etTriggerUrl.setText(components[2]);
chkTriggerUrlUseAuthentication.setChecked(ActivityManageActionTriggerUrl.resultingAction.getParameter1()); chkTriggerUrlUseAuthentication.setChecked(getIntent().getBooleanExtra(ActivityManageRule.intentNameActionParameter1, false));
etTriggerUrlUsername.setText(components[0]); etTriggerUrlUsername.setText(components[0]);
etTriggerUrlPassword.setText(components[1]); etTriggerUrlPassword.setText(components[1]);
@ -251,46 +250,6 @@ public class ActivityManageActionTriggerUrl extends Activity
}); });
} }
private void backToRuleManager()
{
if(edit && resultingAction != null)
{
String username = etTriggerUrlUsername.getText().toString();
String password = etTriggerUrlPassword.getText().toString();
if(username == null)
username = "";
if(password == null)
password = "";
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
ActivityManageActionTriggerUrl.resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
String httpParams = "";
for (String s : httpParamsList)
httpParams += Action.actionParameters2SeparatorOuter + s;
if(httpParams.length() > 0)
httpParams = httpParams.substring(Action.actionParameters2SeparatorOuter.length());
ActivityManageActionTriggerUrl.resultingAction.setParameter2(
username + Action.actionParameter2Split +
password + Action.actionParameter2Split +
etTriggerUrl.getText().toString().trim() + Action.actionParameter2Split +
method + Action.actionParameter2Split +
httpParams
);
//TODO:Duplicate code in save routine in onCreate()
}
setResult(RESULT_OK);
this.finish();
}
private void updateListView() private void updateListView()
{ {
Miscellaneous.logEvent("i", "ListView", "Attempting to update lvTriggerUrlPostParameters", 4); Miscellaneous.logEvent("i", "ListView", "Attempting to update lvTriggerUrlPostParameters", 4);

View File

@ -396,9 +396,11 @@ public class ActivityManageRule extends Activity
break; break;
case triggerUrl: case triggerUrl:
Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class); Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class);
ActivityManageActionTriggerUrl.resultingAction = a; // ActivityManageActionTriggerUrl.resultingAction = a;
ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit); // ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit);
activityEditTriggerUrlIntent.putExtra("edit", true); // activityEditTriggerUrlIntent.putExtra("edit", true);
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter1, a.getParameter1());
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit); startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit);
break; break;
case speakText: case speakText:
@ -1380,12 +1382,13 @@ public class ActivityManageRule extends Activity
if(requestCode == requestCodeActionTriggerUrlAdd) if(requestCode == requestCodeActionTriggerUrlAdd)
{ {
//TODO: Transform into newer and cleaner handover method through intent data
if(resultCode == RESULT_OK) if(resultCode == RESULT_OK)
{ {
//add TriggerUrl newAction.setParentRule(ruleToEdit);
ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit); newAction.setAction(Action_Enum.triggerUrl);
ruleToEdit.getActionSet().add(ActivityManageActionTriggerUrl.resultingAction); newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, true));
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList(); this.refreshActionList();
} }
} }
@ -1393,7 +1396,14 @@ public class ActivityManageRule extends Activity
{ {
if(resultCode == RESULT_OK) if(resultCode == RESULT_OK)
{ {
//edit TriggerUrl ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter1))
ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, true));
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList(); this.refreshActionList();
} }
} }
@ -2246,7 +2256,7 @@ public class ActivityManageRule extends Activity
{ {
//launch other activity to enter a url and parameters; //launch other activity to enter a url and parameters;
newAction.setAction(Action_Enum.triggerUrl); newAction.setAction(Action_Enum.triggerUrl);
ActivityManageActionTriggerUrl.resultingAction = null; // ActivityManageActionTriggerUrl.resultingAction = null;
Intent editTriggerIntent = new Intent(context, ActivityManageActionTriggerUrl.class); Intent editTriggerIntent = new Intent(context, ActivityManageActionTriggerUrl.class);
startActivityForResult(editTriggerIntent, requestCodeActionTriggerUrlAdd); startActivityForResult(editTriggerIntent, requestCodeActionTriggerUrlAdd);
} }

View File

@ -53,6 +53,8 @@ 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: Hint text about multiple rule execution
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);

View File

@ -223,7 +223,7 @@ public class Miscellaneous extends Service
return result.toString(); return result.toString();
} }
public static String downloadURLwithoutCertificateChecking(String url, String username, String password, String method, Map<String, String> httpParams) public static String downloadUrlWithoutCertificateChecking(String url, String username, String password, String method, Map<String, String> httpParams)
{ {
try try
{ {
@ -298,25 +298,9 @@ public class Miscellaneous extends Service
@Override @Override
public IBinder onBind(Intent arg0) public IBinder onBind(Intent arg0)
{ {
// TODO Auto-generated method stub
return null; return null;
} }
// public static void logEvent(String type, String header, String description)
// {
// if(type.equals("e"))
// Log.e(header, description);
//
// if(type.equals("w"))
// Log.w(header, description);
//
// if(type.equals("i"))
// Log.i(header, description);
//
// if(Settings.writeLogFile)
// writeToLogFile(type, header, description);
// }
public static void logEvent(String type, String header, String description, int logLevel) public static void logEvent(String type, String header, String description, int logLevel)
{ {
try try
@ -353,7 +337,6 @@ public class Miscellaneous extends Service
{ {
logCleanerRunning = true; logCleanerRunning = true;
long maxSizeInBytes = (long)Settings.logFileMaxSize * 1024 * 1024; long maxSizeInBytes = (long)Settings.logFileMaxSize * 1024 * 1024;
if(logFile.exists() && logFile.length() > (maxSizeInBytes)) if(logFile.exists() && logFile.length() > (maxSizeInBytes))
@ -1039,17 +1022,11 @@ public class Miscellaneous extends Service
} }
catch (KeyManagementException e) catch (KeyManagementException e)
{ {
// TODO Auto-generated catch block Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4);
e.printStackTrace();
} }
catch (NoSuchAlgorithmException e) catch (NoSuchAlgorithmException e)
{ {
// TODO Auto-generated catch block Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4);
e.printStackTrace();
}
finally
{
} }
} }

View File

@ -684,7 +684,6 @@ public class Trigger
9 = calendarList 9 = calendarList
*/ */
boolean isActive = getTriggerParameter(); boolean isActive = getTriggerParameter();
if (!ignoreActive && isActive != event.isCurrentlyActive()) if (!ignoreActive && isActive != event.isCurrentlyActive())
{ {
@ -756,6 +755,12 @@ public class Trigger
// No contradictions found // No contradictions found
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4); Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
/*
At this point the rule will either get executed for this event or it already has been executed for it.
*/
CalendarReceiver.addUsedPair(new CalendarReceiver.RuleEventPair(getParentRule(), event));
return true; return true;
} }

View File

@ -272,29 +272,23 @@ public class CellLocationChangedReceiver extends PhoneStateListener
locationListenerArmed = false; locationListenerArmed = false;
Miscellaneous.logEvent("i", "LocationListener", "Disarmed location listener, accuracy reached", 4); Miscellaneous.logEvent("i", "LocationListener", "Disarmed location listener, accuracy reached", 4);
} }
// Miscellaneous.logEvent("i", "LocationListener", "Giving update to POI class");
// PointOfInterest.positionUpdate(up2DateLocation, parentLocationProvider.parentService);
} }
@Override @Override
public void onProviderDisabled(String provider) public void onProviderDisabled(String provider)
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void onProviderEnabled(String provider) public void onProviderEnabled(String provider)
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void onStatusChanged(String provider, int status, Bundle extras) public void onStatusChanged(String provider, int status, Bundle extras)
{ {
// TODO Auto-generated method stub
} }
} }

View File

@ -9,8 +9,10 @@ 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.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.jens.automation2.AutomationService; import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous; import com.jens.automation2.Miscellaneous;
@ -29,7 +31,6 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
static CalendarReceiver calendarReceiverInstance = null; static CalendarReceiver calendarReceiverInstance = null;
static boolean calendarReceiverActive = false; static boolean calendarReceiverActive = false;
static IntentFilter calendarIntentFilter = null; static IntentFilter calendarIntentFilter = null;
private static AutomationService automationServiceRef;
private static Intent calendarIntent = null; private static Intent calendarIntent = null;
public static final int AVAILABILITY_OUT_OF_OFFICE = 4; public static final int AVAILABILITY_OUT_OF_OFFICE = 4;
@ -45,6 +46,30 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
static AlarmManager alarmManager = null; static AlarmManager alarmManager = null;
static boolean wakeupNeedsToBeScheduled = false; static boolean wakeupNeedsToBeScheduled = false;
public static class RuleEventPair
{
Rule rule;
CalendarEvent event;
public RuleEventPair(Rule rule, CalendarEvent event)
{
this.rule = rule;
this.event = event;
}
}
static List<RuleEventPair> calendarEventsUsed = new ArrayList<>(); // To determine for which events which rules have been executed
public static void addUsedPair(RuleEventPair pair)
{
// Add pair only if it's not in the list already.
for(RuleEventPair usedPair : calendarEventsUsed)
{
if(usedPair.rule.equals(pair.rule) && usedPair.event.equals(pair.event))
return;
}
calendarEventsUsed.add(pair);
}
public static CalendarReceiver getInstance() public static CalendarReceiver getInstance()
{ {
if(calendarReceiverInstance == null) if(calendarReceiverInstance == null)
@ -73,9 +98,15 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
} }
} }
private static void checkForRules(Context context) static void checkForRules(Context context)
{ {
//TODO: Overwrite notification /*
Kann die selbe Regel mehrfach pro Termin ausgeführt werden? Nein, eh nicht, ne?
Am nächsten Tag ist es wieder ein anderer Termin.
Wenn zwei zeitgleiche Termine mit gleichen Inhalten in verschiedenen Kalendern sind,
würde die Regel so 2x ausgeführt werden.
*/
//TODO: Second appointment directly one after another or overlapping won't get executed //TODO: Second appointment directly one after another or overlapping won't get executed
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent); ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
for (int i = 0; i < ruleCandidates.size(); i++) for (int i = 0; i < ruleCandidates.size(); i++)
@ -86,24 +117,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
} }
@Override @Override
public void startListener(AutomationService automationService) public void startListener(AutomationService automationServiceRef)
{ {
if(!calendarReceiverActive) startCalendarReceiver(automationServiceRef);
{
if(calendarReceiverInstance == null)
calendarReceiverInstance = new CalendarReceiver();
if(calendarIntentFilter == null)
{
calendarIntentFilter = new IntentFilter();
calendarIntentFilter.addAction(Intent.ACTION_PROVIDER_CHANGED);
// calendarIntentFilter.addDataScheme("content");
}
AutomationService.getInstance().registerReceiver(calendarReceiverInstance, calendarIntentFilter);
calendarReceiverActive = true;
}
} }
@Override @Override
@ -171,6 +187,37 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{ {
return title; return title;
} }
@Override
public boolean equals(@Nullable Object obj)
{
try
{
CalendarEvent compareEvent = (CalendarEvent) obj;
return calendarId == compareEvent.calendarId
&&
eventId.equals(compareEvent.eventId)
&&
title.equals(compareEvent.title)
&&
description.equals(compareEvent.description)
&&
location.equals(compareEvent.location)
&&
availability.equals(compareEvent.availability)
&&
start.getTimeInMillis() == compareEvent.start.getTimeInMillis()
&&
end.getTimeInMillis() == compareEvent.end.getTimeInMillis()
&&
allDay == compareEvent.allDay;
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "CalendarReceiver compare()", Log.getStackTraceString(e), 5);
return false;
}
}
} }
public static List<AndroidCalendar> readCalendars(Context context) public static List<AndroidCalendar> readCalendars(Context context)
@ -394,22 +441,22 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
Collections.sort(wakeUpCandidatesList); Collections.sort(wakeUpCandidatesList);
if(wakeUpCandidatesList.size() == 0) if(wakeUpCandidatesList.size() == 0)
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Not scheduling any calendar related wakeup as there are no future events that might match a configured trigger.", 5); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Not scheduling any calendar related wakeup as there are no future events that might match a configured trigger.", 4);
else else
{ {
if (nextWakeup == null || nextWakeup.getTimeInMillis() != wakeUpCandidatesList.get(0)) if (nextWakeup == null || nextWakeup.getTimeInMillis() != wakeUpCandidatesList.get(0))
{ {
Calendar newAlarm = Miscellaneous.calendarFromLong(wakeUpCandidatesList.get(0)); Calendar newAlarm = Miscellaneous.calendarFromLong(wakeUpCandidatesList.get(0));
if (nextWakeup == null) if (nextWakeup == null)
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was null.", 5); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was null.", 4);
else else
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was " + Miscellaneous.formatDate(nextWakeup.getTime()), 5); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was " + Miscellaneous.formatDate(nextWakeup.getTime()), 4);
nextWakeup = newAlarm; nextWakeup = newAlarm;
if (!wakeupNeedsToBeScheduled) if (!wakeupNeedsToBeScheduled)
wakeupNeedsToBeScheduled = true; wakeupNeedsToBeScheduled = true;
} }
else 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); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Alarm " + Miscellaneous.formatDate(nextWakeup.getTime()) + " has been selected as next wakeup, but not rescheduling since this was not a change.", 4);
} }
} }
} }
@ -418,8 +465,6 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{ {
if (!calendarReceiverActive) if (!calendarReceiverActive)
{ {
CalendarReceiver.automationServiceRef = automationServiceRef;
if (calendarReceiverInstance == null) if (calendarReceiverInstance == null)
calendarReceiverInstance = new CalendarReceiver(); calendarReceiverInstance = new CalendarReceiver();
@ -438,4 +483,31 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
armOrRearmTimer(); armOrRearmTimer();
} }
} }
public static boolean mayRuleStillBeActivatedForPendingCalendarEvents(Rule rule)
{
for(CalendarEvent event : readCalendarEvents(Miscellaneous.getAnyContext(), false))
{
for(Trigger t : rule.getTriggerSet())
{
if(t.getTriggerType().equals(Trigger.Trigger_Enum.calendarEvent) && t.checkCalendarEvent(event, false))
{
if (!hasEventBeenUsedInRule(rule, event))
return true;
}
}
}
return false;
}
static boolean hasEventBeenUsedInRule(Rule rule, CalendarEvent event)
{
for (RuleEventPair executedPair : calendarEventsUsed)
{
if (executedPair.rule.equals(rule) && executedPair.event.equals(event))
return true;
}
return false;
}
} }

View File

@ -26,8 +26,6 @@ import java.util.Calendar;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationListener extends NotificationListenerService// implements AutomationListenerInterface public class NotificationListener extends NotificationListenerService// implements AutomationListenerInterface
{ {
static Calendar lastResponseToNotification = null;
static boolean listenerRunning = false;
static NotificationListener instance; static NotificationListener instance;
static SimpleNotification lastNotification = null; static SimpleNotification lastNotification = null;
@ -43,8 +41,6 @@ public class NotificationListener extends NotificationListenerService// implemen
// a bitmap to be used instead of the small icon when showing the notification payload // a bitmap to be used instead of the small icon when showing the notification payload
public static final String EXTRA_LARGE_ICON = "android.largeIcon"; public static final String EXTRA_LARGE_ICON = "android.largeIcon";
protected static IntentFilter notificationReceiverIntentFilter = null;
public static SimpleNotification getLastNotification() public static SimpleNotification getLastNotification()
{ {
return lastNotification; return lastNotification;

View File

@ -2,6 +2,7 @@
* Fixed: Broadcast receiver trigger would not trigger anything, but crash * Fixed: Broadcast receiver trigger would not trigger anything, but crash
* Fixed: Bug in Android 14 (not in Automation!!!) required a change when dialing MMI codes containing a # character. * Fixed: Bug in Android 14 (not in Automation!!!) required a change when dialing MMI codes containing a # character.
* Fixed: Storage permission might be displayed as not granted even if it was * Fixed: Storage permission might be displayed as not granted even if it was
* Fixed: Applied a very old bugfix also to F-Droid and Google-Play editions that had by mistake been implemented only in the APK edition (timeFrame trigger with repetitions)
* Added: new action -> take screenshot * Added: new action -> take screenshot
* Added: Location service (GPS) can be toggled between states if WRITE_SECURE_SETTINGS has been granted from a computer * Added: Location service (GPS) can be toggled between states if WRITE_SECURE_SETTINGS has been granted from a computer
* Added: triggerUrl action can now be used with POST and parameters * Added: triggerUrl action can now be used with POST and parameters