diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index f9040a53..cc7935bd 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,6 +1,17 @@ + + + + + + + + + + + @@ -12,6 +23,6 @@ - + \ No newline at end of file diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index bd5ee2b6..1120377d 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -1,44 +1,22 @@ package com.jens.automation2; +import static com.jens.automation2.Trigger.triggerParameter2Split; + import android.annotation.SuppressLint; -import android.app.Notification; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; import android.os.Looper; -import android.os.Parcelable; -import android.service.notification.StatusBarNotification; -import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.location.DetectedActivity; -import com.jens.automation2.location.LocationProvider; -import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.receivers.ActivityDetectionReceiver; -import com.jens.automation2.receivers.BatteryReceiver; -import com.jens.automation2.receivers.BluetoothReceiver; -import com.jens.automation2.receivers.ConnectivityReceiver; -import com.jens.automation2.receivers.HeadphoneJackListener; -import com.jens.automation2.receivers.NfcReceiver; -import com.jens.automation2.receivers.NoiseListener; -import com.jens.automation2.receivers.NotificationListener; -import com.jens.automation2.receivers.PhoneStatusListener; -import com.jens.automation2.receivers.ProcessListener; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import static com.jens.automation2.Trigger.triggerParameter2Split; - -import androidx.core.app.NotificationCompat; - -import org.apache.commons.lang3.StringUtils; - public class Rule implements Comparable { @@ -356,6 +334,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -461,32 +450,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -497,9 +460,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java index 90ca7e6c..f20ec687 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java +++ b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java @@ -294,7 +294,7 @@ public class ActivityDetectionReceiver extends IntentService implements Automati ArrayList allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection(); for(int i=0; i { @@ -357,6 +341,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -370,538 +365,8 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.pointOfInterest)) - { - // Am I here? - PointOfInterest activePoi = PointOfInterest.getActivePoi(); - if(activePoi != null) //entering one - { - if(oneTrigger.getPointOfInterest() != null) - { - if(activePoi.equals(oneTrigger.getPointOfInterest())) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're entering POI: " + oneTrigger.getPointOfInterest().getName() + ", not leaving it.", 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + oneTrigger.getPointOfInterest().getName() + ".", 4); - return false; - } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); - return false; - } - } - } - else //leaving one - { - // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. - if(oneTrigger.getPointOfInterest() != null) - { -// if(activePoi.equals(oneTrigger.getPointOfInterest())) -// { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "We are not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\".", 3); - return false; - } -// } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); - return false; - } - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) - { - Date now = new Date(); - String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds()); - Time nowTime = Time.valueOf(timeString); - Calendar calNow = Calendar.getInstance(); - - - if(oneTrigger.getTimeFrame().getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK))) - { - if( - // Regular case, start time is lower than end time - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - && - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0 - ) - || - // Other case, start time higher than end time, timeframe goes over midnight - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), oneTrigger.getTimeFrame().getTriggerTimeStop()) < 0 - && - (Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - || - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0) - ) - - ) - { - // We are in the timeframe - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + "). Trigger of Rule " + this.getName() + " applies.", 3); - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 3); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 3); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the time. Trigger of Rule " + this.getName() + " doesn\'t apply..", 5); - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 5); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 5); - return false; - } - // return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the day. Trigger of Rule " + this.getName() + " doesn\'t apply.", 5); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.charging)) - { - if(BatteryReceiver.isDeviceCharging(context) == 0) - { - return false; // unknown charging state, can't activate rule under these conditions - } - else if(BatteryReceiver.isDeviceCharging(context) == 1) - { - if(oneTrigger.getTriggerParameter()) //rule says when charging, but we're currently discharging - return false; - } - else if(BatteryReceiver.isDeviceCharging(context) == 2) - { - if(!oneTrigger.getTriggerParameter()) //rule says when discharging, but we're currently charging - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.usb_host_connection)) - { - if(BatteryReceiver.isUsbHostConnected() != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.batteryLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(BatteryReceiver.getBatteryLevel() <= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - else - { - if(oneTrigger.getBatteryLevel() >= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.speed)) - { - if(oneTrigger.getTriggerParameter()) - { - if(LocationProvider.getSpeed() < oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - else - { - if(LocationProvider.getSpeed() > oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.noiseLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(NoiseListener.getNoiseLevelDb() < oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - else - { - if(NoiseListener.getNoiseLevelDb() > oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.wifiConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for wifi state", 4); - if(oneTrigger.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected - { - if(oneTrigger.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name specified, checking that.", 4); - if(!WifiBroadcastReceiver.getLastWifiSsid().equals(oneTrigger.getTriggerParameter2())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), oneTrigger.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); - return false; - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name matches. Rule will apply.", 4); - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "No wifi name specified, any will do.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi state not correct, demanded " + String.valueOf(oneTrigger.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.process_started_stopped)) - { - boolean running = ProcessListener.getRunningApps().contains(oneTrigger.getProcessName()); - - if(running) - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is currently running.", 4); - else - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is not running.", 4); - - if(running != oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); - return false; - } - - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.airplaneMode)) - { - if(ConnectivityReceiver.isAirplaneMode(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.roaming)) - { - if(ConnectivityReceiver.isRoaming(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.phoneCall)) - { - String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - // state dir number - - if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) - { - //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) - if( - (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) - ) - { - if( - elements[1].equals(Trigger.triggerPhoneCallDirectionAny) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) - ) - { - // Trigger conditions are met - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(oneTrigger.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(oneTrigger.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + oneTrigger.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.nfcTag)) - { - if(NfcReceiver.lastReadLabel == null) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); - return false; - } - else if(!NfcReceiver.lastReadLabel.equals(oneTrigger.getNfcTagId())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + oneTrigger.getNfcTagId(), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.bluetoothConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for bluetooth...", 4); - - if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() != oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() == oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().length() > 0) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.headsetPlugged)) - { - if(HeadphoneJackListener.isHeadsetConnected() != oneTrigger.getTriggerParameter()) - return false; - else - if(oneTrigger.getHeadphoneType() != 2 && oneTrigger.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.notification)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { - String[] params = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText; - if (params.length >= 5) - requiredText = params[4]; - else - requiredText = ""; - - if(oneTrigger.getTriggerParameter()) - { - // Check an active notification that is still there - - boolean foundMatch = false; - - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - if(getLastExecution() == null || sbn.getPostTime() > this.lastExecution.getTimeInMillis()) - { - String notificationApp = sbn.getPackageName(); - String notificationTitle = null; - String notificationText = null; - - Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); - - if (!myApp.equals("-1")) - { - if (!notificationApp.equalsIgnoreCase(myApp)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - /* - If there are multiple notifications ("stacked") title or text might be null: - https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications - */ - - Bundle extras = sbn.getNotification().extras; - - // T I T L E - if (extras.containsKey(EXTRA_TITLE)) - notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); - - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); - - // T E X T - - if (extras.containsKey(EXTRA_TEXT)) - notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); - - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); - - foundMatch = true; - break; - } - } - - if(!foundMatch) - return false; - } - else - { - // check a notification that is gone - - if(NotificationListener.getLastNotification() != null) - { - if(!NotificationListener.getLastNotification().isCreated()) - { - String app = NotificationListener.getLastNotification().getApp(); - String title = NotificationListener.getLastNotification().getTitle(); - String text = NotificationListener.getLastNotification().getText(); - - if (!myApp.equals("-1")) - { - if (!app.equalsIgnoreCase(myApp)) - return false; - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - if (requiredTitle.length() > 0) - { - if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) - return false; - } - - if (requiredText.length() > 0) - { - if (!Miscellaneous.compare(myTextDir, text, requiredText)) - return false; - } - } - else - return false; - } - } - } - } + if (!oneTrigger.applies(null, context)) + return false; } return true; @@ -960,32 +425,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -996,9 +435,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java index e541dc72..4a4fa69b 100644 --- a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java @@ -1,46 +1,22 @@ package com.jens.automation2; +import static com.jens.automation2.Trigger.triggerParameter2Split; + import android.annotation.SuppressLint; -import android.app.Notification; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; import android.os.Looper; -import android.os.Parcelable; -import android.service.notification.StatusBarNotification; -import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.location.DetectedActivity; -import com.jens.automation2.location.LocationProvider; -import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.receivers.ActivityDetectionReceiver; -import com.jens.automation2.receivers.BatteryReceiver; -import com.jens.automation2.receivers.BluetoothReceiver; -import com.jens.automation2.receivers.ConnectivityReceiver; -import com.jens.automation2.receivers.HeadphoneJackListener; -import com.jens.automation2.receivers.NfcReceiver; -import com.jens.automation2.receivers.NoiseListener; -import com.jens.automation2.receivers.NotificationListener; -import com.jens.automation2.receivers.PhoneStatusListener; -import com.jens.automation2.receivers.ProcessListener; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import static com.jens.automation2.Trigger.triggerParameter2Split; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE; - -import androidx.core.app.NotificationCompat; - -import org.apache.commons.lang3.StringUtils; - public class Rule implements Comparable { @@ -358,6 +334,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -371,344 +358,27 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.pointOfInterest)) + if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) { - // Am I here? - PointOfInterest activePoi = PointOfInterest.getActivePoi(); - if(activePoi != null) //entering one - { - if(oneTrigger.getPointOfInterest() != null) - { - if(activePoi.equals(oneTrigger.getPointOfInterest())) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're entering POI: " + oneTrigger.getPointOfInterest().getName() + ", not leaving it.", 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + oneTrigger.getPointOfInterest().getName() + ".", 4); - return false; - } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); - return false; - } - } - } - else //leaving one - { - // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. - if(oneTrigger.getPointOfInterest() != null) - { -// if(activePoi.equals(oneTrigger.getPointOfInterest())) -// { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "We are not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\".", 3); - return false; - } -// } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); - return false; - } - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) - { - Date now = new Date(); - String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds()); - Time nowTime = Time.valueOf(timeString); - Calendar calNow = Calendar.getInstance(); - - - if(oneTrigger.getTimeFrame().getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK))) - { - if( - // Regular case, start time is lower than end time - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - && - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0 - ) - || - // Other case, start time higher than end time, timeframe goes over midnight - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), oneTrigger.getTimeFrame().getTriggerTimeStop()) < 0 - && - (Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - || - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0) - ) - - ) - { - // We are in the timeframe - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + "). Trigger of Rule " + this.getName() + " applies.", 3); - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 3); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 3); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the time. Trigger of Rule " + this.getName() + " doesn\'t apply..", 5); - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 5); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 5); - return false; - } - // return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the day. Trigger of Rule " + this.getName() + " doesn\'t apply.", 5); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.charging)) - { - if(BatteryReceiver.isDeviceCharging(context) == 0) - { - return false; // unknown charging state, can't activate rule under these conditions - } - else if(BatteryReceiver.isDeviceCharging(context) == 1) - { - if(oneTrigger.getTriggerParameter()) //rule says when charging, but we're currently discharging - return false; - } - else if(BatteryReceiver.isDeviceCharging(context) == 2) - { - if(!oneTrigger.getTriggerParameter()) //rule says when discharging, but we're currently charging - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.usb_host_connection)) - { - if(BatteryReceiver.isUsbHostConnected() != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.batteryLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(BatteryReceiver.getBatteryLevel() <= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - else - { - if(oneTrigger.getBatteryLevel() >= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.speed)) - { - if(oneTrigger.getTriggerParameter()) - { - if(LocationProvider.getSpeed() < oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - else - { - if(LocationProvider.getSpeed() > oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.noiseLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(NoiseListener.getNoiseLevelDb() < oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - else - { - if(NoiseListener.getNoiseLevelDb() > oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.wifiConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for wifi state", 4); - if(oneTrigger.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected - { - if(oneTrigger.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name specified, checking that.", 4); - if(!WifiBroadcastReceiver.getLastWifiSsid().equals(oneTrigger.getTriggerParameter2())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), oneTrigger.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); - return false; - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name matches. Rule will apply.", 4); - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "No wifi name specified, any will do.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi state not correct, demanded " + String.valueOf(oneTrigger.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.process_started_stopped)) - { - boolean running = ProcessListener.getRunningApps().contains(oneTrigger.getProcessName()); - - if(running) - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is currently running.", 4); - else - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is not running.", 4); - - if(running != oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); - return false; - } - - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.airplaneMode)) - { - if(ConnectivityReceiver.isAirplaneMode(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.roaming)) - { - if(ConnectivityReceiver.isRoaming(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.phoneCall)) - { - String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - // state dir number - - if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) - { - //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) - if( - (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) - ) - { - if( - elements[1].equals(Trigger.triggerPhoneCallDirectionAny) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) - ) - { - // Trigger conditions are met - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(oneTrigger.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(oneTrigger.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + oneTrigger.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.nfcTag)) - { - if(NfcReceiver.lastReadLabel == null) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); - return false; - } - else if(!NfcReceiver.lastReadLabel.equals(oneTrigger.getNfcTagId())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + oneTrigger.getNfcTagId(), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) - { - if(ActivityDetectionReceiver.getActivityDetectionLastResult() != null) + if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) { boolean found = false; - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) found = true; } - if(!found) + if (!found) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); return false; } else { - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); return false; @@ -717,220 +387,10 @@ public class Rule implements Comparable } } } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.bluetoothConnection)) + else { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for bluetooth...", 4); - - if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() != oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() == oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().length() > 0) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); + if (!oneTrigger.applies(null, context)) return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.headsetPlugged)) - { - if(HeadphoneJackListener.isHeadsetConnected() != oneTrigger.getTriggerParameter()) - return false; - else - if(oneTrigger.getHeadphoneType() != 2 && oneTrigger.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.notification)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { - String[] params = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText; - if (params.length >= 5) - requiredText = params[4]; - else - requiredText = ""; - - if(oneTrigger.getTriggerParameter()) - { - // Check an active notification that is still there - - boolean foundMatch = false; - - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - if(getLastExecution() == null || sbn.getPostTime() > this.lastExecution.getTimeInMillis()) - { - String notificationApp = sbn.getPackageName(); - String notificationTitle = null; - String notificationText = null; - - Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); - - if (!myApp.equals("-1")) - { - if (!notificationApp.equalsIgnoreCase(myApp)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - /* - If there are multiple notifications ("stacked") title or text might be null: - https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications - */ - - Bundle extras = sbn.getNotification().extras; - - // T I T L E - if (extras.containsKey(EXTRA_TITLE)) - notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); - - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); - - // T E X T - - if (extras.containsKey(EXTRA_TEXT)) - notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); - - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); - - foundMatch = true; - break; - } - } - - if(!foundMatch) - return false; - } - else - { - // check a notification that is gone - - if(NotificationListener.getLastNotification() != null) - { - if(!NotificationListener.getLastNotification().isCreated()) - { - String app = NotificationListener.getLastNotification().getApp(); - String title = NotificationListener.getLastNotification().getTitle(); - String text = NotificationListener.getLastNotification().getText(); - - if (!myApp.equals("-1")) - { - if (!app.equalsIgnoreCase(myApp)) - return false; - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - if (requiredTitle.length() > 0) - { - if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) - return false; - } - - if (requiredText.length() > 0) - { - if (!Miscellaneous.compare(myTextDir, text, requiredText)) - return false; - } - } - else - return false; - } - } - } } } @@ -990,32 +450,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -1026,9 +460,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/main/java/com/jens/automation2/PointOfInterest.java b/app/src/main/java/com/jens/automation2/PointOfInterest.java index 7a42031a..edf39597 100644 --- a/app/src/main/java/com/jens/automation2/PointOfInterest.java +++ b/app/src/main/java/com/jens/automation2/PointOfInterest.java @@ -264,7 +264,7 @@ public class PointOfInterest implements Comparable for(int i=0; i Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2); for(int i=0; i was state different in previous step - - try - { - switch(getTriggerType()) - { - case timeFrame: - if(!checkDateTime(triggeringObject, true)) - return false; - break; - default: - break; - } - + if(getParentRule().getLastExecution() == null) return true; - } - catch(Exception e) + else if(lastTimeNotApplied != null) { - Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.getParentRule().toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); - return false; + if(lastTimeNotApplied.getTimeInMillis() > getParentRule().getLastExecution().getTimeInMillis()) + { + return true; + } } + + return false; } boolean checkCharging() diff --git a/app/src/main/java/com/jens/automation2/location/LocationProvider.java b/app/src/main/java/com/jens/automation2/location/LocationProvider.java index 8a2956ec..d50ac70b 100644 --- a/app/src/main/java/com/jens/automation2/location/LocationProvider.java +++ b/app/src/main/java/com/jens/automation2/location/LocationProvider.java @@ -201,7 +201,7 @@ public class LocationProvider ArrayList ruleCandidates = Rule.findRuleCandidatesBySpeed(); for (Rule oneRule : ruleCandidates) { - if (oneRule.applies(this.getParentService())) + if (oneRule.applies(this.getParentService()) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(getParentService(), false); } } diff --git a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java index c2b2ea53..b8a9a8c7 100644 --- a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java @@ -147,7 +147,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver ArrayList ruleCandidates = Rule.findRuleCandidatesByWifiConnection(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationServiceInstance)) + if(oneRule.applies(automationServiceInstance) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java index 0d75214d..9d2de54e 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java @@ -206,7 +206,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByCharging(true); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByBatteryLevel(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByCharging(false); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByUsbHost(true); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context)) + if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceRef, false); } @@ -278,7 +278,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByUsbHost(false); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context)) + if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceRef, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java index 0415c781..0abc46b9 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java @@ -127,7 +127,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi ArrayList ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming); for(int i=0; i allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime); for(int i=0; i ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.devicePosition); for (int i = 0; i < ruleCandidates.size(); i++) { - if (ruleCandidates.get(i).applies(Miscellaneous.getAnyContext())) + if (ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java index fc377183..807fcd41 100644 --- a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java @@ -77,7 +77,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati ArrayList ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected()); for(int i=0; i allRulesWithNfcTags = Rule.findRuleCandidatesByNfc(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByNoiseLevel(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationService)) + if(oneRule.applies(automationService) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationService, false); } } 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 8daaf344..f3d97b06 100644 --- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java @@ -96,7 +96,7 @@ public class NotificationListener extends NotificationListenerService ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification); for (int i = 0; i < ruleCandidates.size(); i++) { - if (ruleCandidates.get(i).applies(NotificationListener.this)) + if (ruleCandidates.get(i).applies(NotificationListener.this) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } // } diff --git a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java index ae67a2f8..9e9f4100 100644 --- a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java @@ -114,7 +114,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance)) + if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -146,7 +146,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if (asInstance != null) - if (ruleCandidates.get(i).applies(asInstance)) + if (ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -183,7 +183,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance)) + if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java index 42778dc6..4390ea0b 100644 --- a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java @@ -62,7 +62,7 @@ public class ProcessListener implements AutomationListenerInterface ArrayList ruleCandidates = Rule.findRuleCandidatesByProcess(); for(int i=0; i