diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml index 84b71d8..baa18f9 100644 --- a/app/src/apkFlavor/AndroidManifest.xml +++ b/app/src/apkFlavor/AndroidManifest.xml @@ -139,6 +139,7 @@ @@ -151,6 +152,7 @@ @@ -193,6 +195,7 @@ @@ -242,6 +245,7 @@ diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index cfb6204..8112d2d 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -10,9 +10,12 @@ import android.os.Looper; import android.util.Log; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.google.android.gms.location.DetectedActivity; import com.jens.automation2.receivers.ActivityDetectionReceiver; import com.jens.automation2.receivers.BroadcastListener; +import com.jens.automation2.receivers.CalendarReceiver; import java.util.ArrayList; import java.util.Calendar; @@ -376,6 +379,11 @@ public class Rule implements Comparable Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4); 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 Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4); } @@ -384,7 +392,7 @@ public class Rule implements Comparable return false; } - + public boolean applies(Context context) { if(AutomationService.getInstance() == null) @@ -780,4 +788,32 @@ public class Rule implements Comparable 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; + } } \ No newline at end of file diff --git a/app/src/fdroidFlavor/AndroidManifest.xml b/app/src/fdroidFlavor/AndroidManifest.xml index f110910..8f55e80 100644 --- a/app/src/fdroidFlavor/AndroidManifest.xml +++ b/app/src/fdroidFlavor/AndroidManifest.xml @@ -136,6 +136,7 @@ @@ -148,6 +149,7 @@ @@ -190,6 +192,7 @@ @@ -239,6 +242,7 @@ diff --git a/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java b/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java index c28d366..4591e5f 100644 --- a/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java @@ -344,7 +344,16 @@ public class Rule implements Comparable if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) { if(oneTrigger.getTimeFrame().repetition > 0) - return true; + { + if(this.getLastExecution() != null) + { + Calendar now = Calendar.getInstance(); + if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis()) + return true; + } + else + return true; + } } else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived)) { @@ -372,7 +381,7 @@ public class Rule implements Comparable return false; } - + public boolean applies(Context context) { if(AutomationService.getInstance() == null) diff --git a/app/src/googlePlayFlavor/AndroidManifest.xml b/app/src/googlePlayFlavor/AndroidManifest.xml index 3c2fa65..7a21d7b 100644 --- a/app/src/googlePlayFlavor/AndroidManifest.xml +++ b/app/src/googlePlayFlavor/AndroidManifest.xml @@ -172,7 +172,6 @@ - + if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) { if(oneTrigger.getTimeFrame().repetition > 0) - return true; + { + if(this.getLastExecution() != null) + { + Calendar now = Calendar.getInstance(); + if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis()) + return true; + } + else + return true; + } } else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived)) { diff --git a/app/src/main/java/com/jens/automation2/Action.java b/app/src/main/java/com/jens/automation2/Action.java index 0aa93f0..0c18539 100644 --- a/app/src/main/java/com/jens/automation2/Action.java +++ b/app/src/main/java/com/jens/automation2/Action.java @@ -345,16 +345,33 @@ public class Action 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) { + returnString.append(" ("); + if(components.length >= 4) + returnString.append(components[3]); + else + returnString.append(ActivityManageActionTriggerUrl.methodGet); + returnString.append(")"); + returnString.append(": " + components[2]); if (parameter1) returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + "."); } else + { + returnString.append(" ("); + returnString.append(ActivityManageActionTriggerUrl.methodGet);; + returnString.append(")"); returnString.append(": " + components[0]); + } } else if (this.getAction().equals(Action_Enum.startOtherActivity)) { @@ -786,7 +803,7 @@ public class Action if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https")) response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method, httpParams); else - response = Miscellaneous.downloadURLwithoutCertificateChecking(urlString, urlUsername, urlPassword, method, httpParams); + response = Miscellaneous.downloadUrlWithoutCertificateChecking(urlString, urlUsername, urlPassword, method, httpParams); try { diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionSetVariable.java b/app/src/main/java/com/jens/automation2/ActivityManageActionSetVariable.java index fcff468..89a6813 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionSetVariable.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionSetVariable.java @@ -1,6 +1,6 @@ package com.jens.automation2; -import static com.jens.automation2.ActivityManageActionTriggerUrl.edit; +//import static com.jens.automation2.ActivityManageActionTriggerUrl.edit; import android.app.Activity; import android.content.Intent; diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java b/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java index b8d27da..9cb537f 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java @@ -3,6 +3,7 @@ package com.jens.automation2; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.view.View; @@ -45,8 +46,8 @@ public class ActivityManageActionTriggerUrl extends Activity public static final String methodGet = "GET"; public static final String methodPost = "POST"; - public static boolean edit = false; - public static Action resultingAction = null; +// public static boolean edit = false; +// public static Action resultingAction = null; @Override protected void onCreate(Bundle savedInstanceState) @@ -95,11 +96,9 @@ public class ActivityManageActionTriggerUrl extends Activity { if(etTriggerUrl.getText().toString().length() > 0) { - if(resultingAction == null) - resultingAction = new Action(); + Intent returnIntent = new Intent(); - resultingAction.setAction(Action_Enum.triggerUrl); - resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked()); + returnIntent.putExtra(ActivityManageRule.intentNameActionParameter1, chkTriggerUrlUseAuthentication.isChecked()); String username = etTriggerUrlUsername.getText().toString(); String password = etTriggerUrlPassword.getText().toString(); @@ -120,15 +119,16 @@ public class ActivityManageActionTriggerUrl extends Activity if(httpParams.length() > 0) httpParams = httpParams.substring(Action.actionParameters2SeparatorOuter.length()); - ActivityManageActionTriggerUrl.resultingAction.setParameter2( + returnIntent.putExtra(ActivityManageRule.intentNameActionParameter2, username + Action.actionParameter2Split + password + Action.actionParameter2Split + etTriggerUrl.getText().toString().trim() + Action.actionParameter2Split + method + Action.actionParameter2Split + httpParams ); -//TODO: Check if http params listview is scrollable - backToRuleManager(); + + setResult(RESULT_OK, returnIntent); + finish(); } else Toast.makeText(getBaseContext(), getResources().getString(R.string.urlTooShort), Toast.LENGTH_LONG).show(); @@ -169,22 +169,21 @@ public class ActivityManageActionTriggerUrl extends Activity } }); updateListView(); - - ActivityManageActionTriggerUrl.edit = getIntent().getBooleanExtra("edit", false); - if(edit) + + if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2)) { // username,password,URL,etc. String[] components; - if(ActivityManageActionTriggerUrl.resultingAction.getParameter2().contains(Action.actionParameter2Split)) - components = ActivityManageActionTriggerUrl.resultingAction.getParameter2().split(Action.actionParameter2Split, -1); + if(getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).contains(Action.actionParameter2Split)) + components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(Action.actionParameter2Split, -1); else - components = ActivityManageActionTriggerUrl.resultingAction.getParameter2().split(";", -1); + components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(";", -1); if(components.length >= 3) { - etTriggerUrl.setText(components[2]); - chkTriggerUrlUseAuthentication.setChecked(ActivityManageActionTriggerUrl.resultingAction.getParameter1()); + etTriggerUrl.setText(components[2]); + chkTriggerUrlUseAuthentication.setChecked(getIntent().getBooleanExtra(ActivityManageRule.intentNameActionParameter1, false)); etTriggerUrlUsername.setText(components[0]); etTriggerUrlPassword.setText(components[1]); @@ -250,47 +249,7 @@ 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() { Miscellaneous.logEvent("i", "ListView", "Attempting to update lvTriggerUrlPostParameters", 4); diff --git a/app/src/main/java/com/jens/automation2/ActivityManageRule.java b/app/src/main/java/com/jens/automation2/ActivityManageRule.java index c1ae6bb..a6723de 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageRule.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageRule.java @@ -396,9 +396,11 @@ public class ActivityManageRule extends Activity break; case triggerUrl: Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class); - ActivityManageActionTriggerUrl.resultingAction = a; - ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit); - activityEditTriggerUrlIntent.putExtra("edit", true); +// ActivityManageActionTriggerUrl.resultingAction = a; +// ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit); +// activityEditTriggerUrlIntent.putExtra("edit", true); + activityEditTriggerUrlIntent.putExtra(intentNameActionParameter1, a.getParameter1()); + activityEditTriggerUrlIntent.putExtra(intentNameActionParameter2, a.getParameter2()); startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit); break; case speakText: @@ -1380,12 +1382,13 @@ public class ActivityManageRule extends Activity if(requestCode == requestCodeActionTriggerUrlAdd) { - //TODO: Transform into newer and cleaner handover method through intent data if(resultCode == RESULT_OK) { - //add TriggerUrl - ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit); - ruleToEdit.getActionSet().add(ActivityManageActionTriggerUrl.resultingAction); + newAction.setParentRule(ruleToEdit); + newAction.setAction(Action_Enum.triggerUrl); + newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, true)); + newAction.setParameter2(data.getStringExtra(intentNameActionParameter2)); + ruleToEdit.getActionSet().add(newAction); this.refreshActionList(); } } @@ -1393,7 +1396,14 @@ public class ActivityManageRule extends Activity { 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(); } } @@ -2246,7 +2256,7 @@ public class ActivityManageRule extends Activity { //launch other activity to enter a url and parameters; newAction.setAction(Action_Enum.triggerUrl); - ActivityManageActionTriggerUrl.resultingAction = null; +// ActivityManageActionTriggerUrl.resultingAction = null; Intent editTriggerIntent = new Intent(context, ActivityManageActionTriggerUrl.class); startActivityForResult(editTriggerIntent, requestCodeActionTriggerUrlAdd); } diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java index 08a61e0..f6343ab 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerCalendar.java @@ -53,6 +53,8 @@ public class ActivityManageTriggerCalendar extends Activity Miscellaneous.setDisplayLanguage(this); setContentView(R.layout.activity_manage_trigger_calendar); + //TODO: Hint text about multiple rule execution + chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive); spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection); spinnerCalendarLocationDirection = (Spinner)findViewById(R.id.spinnerCalendarLocationDirection); diff --git a/app/src/main/java/com/jens/automation2/Miscellaneous.java b/app/src/main/java/com/jens/automation2/Miscellaneous.java index 652973d..aafe786 100644 --- a/app/src/main/java/com/jens/automation2/Miscellaneous.java +++ b/app/src/main/java/com/jens/automation2/Miscellaneous.java @@ -223,7 +223,7 @@ public class Miscellaneous extends Service return result.toString(); } - public static String downloadURLwithoutCertificateChecking(String url, String username, String password, String method, Map httpParams) + public static String downloadUrlWithoutCertificateChecking(String url, String username, String password, String method, Map httpParams) { try { @@ -298,25 +298,9 @@ public class Miscellaneous extends Service @Override public IBinder onBind(Intent arg0) { - // TODO Auto-generated method stub 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) { try @@ -353,7 +337,6 @@ public class Miscellaneous extends Service { logCleanerRunning = true; - long maxSizeInBytes = (long)Settings.logFileMaxSize * 1024 * 1024; if(logFile.exists() && logFile.length() > (maxSizeInBytes)) @@ -1006,51 +989,45 @@ public class Miscellaneous extends Service private static void disableSSLCertificateChecking() { try - { - SSLSocketFactory ssf = null; - - try - { - SSLContext ctx = SSLContext.getInstance("TLS"); - - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustStore.load(null, null); - ssf = new MySSLSocketFactoryInsecure(trustStore); - ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - ctx.init(null, null, null); + { + SSLSocketFactory ssf = null; + + try + { + SSLContext ctx = SSLContext.getInstance("TLS"); + + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + ssf = new MySSLSocketFactoryInsecure(trustStore); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ctx.init(null, null, null); // return new DefaultHttpClient(ccm, client.getParams()); - } - catch (Exception ex) - { - ex.printStackTrace(); + } + catch (Exception ex) + { + ex.printStackTrace(); // return null; - } - - // Install the all-trusting trust manager - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, getInsecureTrustManager(), new java.security.SecureRandom()); + } + + // Install the all-trusting trust manager + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, getInsecureTrustManager(), new java.security.SecureRandom()); // HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // HttpsURLConnection.setDefaultSSLSocketFactory(ssf); - - // Install the all-trusting host verifier - HttpsURLConnection.setDefaultHostnameVerifier(getInsecureHostnameVerifier()); - HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - } - catch (KeyManagementException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (NoSuchAlgorithmException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - finally - { - - } + + // Install the all-trusting host verifier + HttpsURLConnection.setDefaultHostnameVerifier(getInsecureHostnameVerifier()); + HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } + catch (KeyManagementException e) + { + Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4); + } + catch (NoSuchAlgorithmException e) + { + Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4); + } } public static TrustManager[] getInsecureTrustManager() diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index b8d187d..71e616c 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -684,7 +684,6 @@ public class Trigger 9 = calendarList */ - boolean isActive = getTriggerParameter(); if (!ignoreActive && isActive != event.isCurrentlyActive()) { @@ -756,6 +755,12 @@ public class Trigger // No contradictions found 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; } diff --git a/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java b/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java index e3b7015..0e61555 100644 --- a/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/CellLocationChangedReceiver.java @@ -272,29 +272,23 @@ public class CellLocationChangedReceiver extends PhoneStateListener locationListenerArmed = false; 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 public void onProviderDisabled(String provider) { - // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { - // TODO Auto-generated method stub } @Override public void onStatusChanged(String provider, int status, Bundle extras) { - // TODO Auto-generated method stub } } 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 1c251ec..ca7369c 100644 --- a/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/CalendarReceiver.java @@ -9,8 +9,10 @@ import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.jens.automation2.AutomationService; import com.jens.automation2.Miscellaneous; @@ -29,7 +31,6 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis static CalendarReceiver calendarReceiverInstance = null; static boolean calendarReceiverActive = false; static IntentFilter calendarIntentFilter = null; - private static AutomationService automationServiceRef; private static Intent calendarIntent = null; 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 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 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() { 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 ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent); for (int i = 0; i < ruleCandidates.size(); i++) @@ -86,24 +117,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis } @Override - public void startListener(AutomationService automationService) + public void startListener(AutomationService automationServiceRef) { - if(!calendarReceiverActive) - { - 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; - } + startCalendarReceiver(automationServiceRef); } @Override @@ -171,6 +187,37 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis { 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 readCalendars(Context context) @@ -394,22 +441,22 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis Collections.sort(wakeUpCandidatesList); 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 { 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); + Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was null.", 4); 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; 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); + 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) { - CalendarReceiver.automationServiceRef = automationServiceRef; - if (calendarReceiverInstance == null) calendarReceiverInstance = new CalendarReceiver(); @@ -438,4 +483,31 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis 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; + } } \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java index b81adf9..60073bf 100644 --- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java @@ -26,8 +26,6 @@ import java.util.Calendar; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public class NotificationListener extends NotificationListenerService// implements AutomationListenerInterface { - static Calendar lastResponseToNotification = null; - static boolean listenerRunning = false; static NotificationListener instance; 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 public static final String EXTRA_LARGE_ICON = "android.largeIcon"; - protected static IntentFilter notificationReceiverIntentFilter = null; - public static SimpleNotification getLastNotification() { return lastNotification; diff --git a/fastlane/metadata/android/en-US/changelogs/138.txt b/fastlane/metadata/android/en-US/changelogs/138.txt index 0645867..83b0f6e 100644 --- a/fastlane/metadata/android/en-US/changelogs/138.txt +++ b/fastlane/metadata/android/en-US/changelogs/138.txt @@ -2,6 +2,7 @@ * 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: 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: 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