Merge remote-tracking branch 'origin/transfer_applies_to_trigger' into development
This commit is contained in:
commit
359dd545c7
17
.idea/deploymentTargetDropDown.xml
generated
17
.idea/deploymentTargetDropDown.xml
generated
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\jens\.android\avd\Android_11.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2021-11-26T17:59:37.692012Z" />
|
||||
</component>
|
||||
</project>
|
@ -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<Rule>
|
||||
{
|
||||
@ -358,6 +334,22 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasNotAppliedSinceLastExecution()
|
||||
{
|
||||
for(Trigger oneTrigger : this.getTriggerSet())
|
||||
{
|
||||
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getsGreenLight(Context context)
|
||||
{
|
||||
return applies(context) && hasNotAppliedSinceLastExecution();
|
||||
}
|
||||
|
||||
public boolean applies(Context context)
|
||||
{
|
||||
@ -371,567 +363,8 @@ public class Rule implements Comparable<Rule>
|
||||
{
|
||||
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.activityDetection))
|
||||
{
|
||||
if(ActivityDetectionReceiver.getActivityDetectionLastResult() != null)
|
||||
{
|
||||
boolean found = false;
|
||||
for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities())
|
||||
{
|
||||
if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType())
|
||||
found = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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("<any>"))
|
||||
{
|
||||
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("<none>"))
|
||||
{
|
||||
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;
|
||||
@ -941,6 +374,44 @@ public class Rule implements Comparable<Rule>
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not.
|
||||
* Hence it is here.
|
||||
* @param oneTrigger
|
||||
* @return
|
||||
*/
|
||||
boolean checkActivityDetection(Trigger oneTrigger)
|
||||
{
|
||||
if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null)
|
||||
{
|
||||
boolean found = false;
|
||||
for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities())
|
||||
{
|
||||
if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType())
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().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)
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class ActivateRuleTask extends AsyncTask<Object, String, Void>
|
||||
{
|
||||
boolean wasActivated = false;
|
||||
@ -958,7 +429,8 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
if (Looper.myLooper() == null)
|
||||
Looper.prepare();
|
||||
|
||||
|
||||
setLastExecution(Calendar.getInstance());
|
||||
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
|
||||
|
||||
return null;
|
||||
@ -983,39 +455,13 @@ public class Rule implements Comparable<Rule>
|
||||
*/
|
||||
if(wasActivated)
|
||||
{
|
||||
setLastExecution(Calendar.getInstance());
|
||||
// setLastExecution(Calendar.getInstance());
|
||||
AutomationService.updateNotification();
|
||||
ActivityMainScreen.updateMainScreen();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
||||
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,10 +472,10 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
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)
|
||||
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
|
||||
@ -1058,6 +504,7 @@ public class Rule implements Comparable<Rule>
|
||||
{
|
||||
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
|
||||
Rule.lastActivatedRuleActivationTime = new Date();
|
||||
|
||||
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
|
||||
ruleRunHistory.remove(ruleRunHistory.size()-1);
|
||||
String history = "";
|
||||
@ -1073,12 +520,12 @@ public class Rule implements Comparable<Rule>
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
return false;
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ public class ActivityDetectionReceiver extends IntentService implements Automati
|
||||
ArrayList<Rule> allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection();
|
||||
for(int i=0; i<allRulesWithActivityDetection.size(); i++)
|
||||
{
|
||||
if(allRulesWithActivityDetection.get(i).applies(Miscellaneous.getAnyContext()))
|
||||
if(allRulesWithActivityDetection.get(i).getsGreenLight(Miscellaneous.getAnyContext()))
|
||||
allRulesWithActivityDetection.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,18 @@
|
||||
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.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<Rule>
|
||||
{
|
||||
@ -357,6 +330,22 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasNotAppliedSinceLastExecution()
|
||||
{
|
||||
for(Trigger oneTrigger : this.getTriggerSet())
|
||||
{
|
||||
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getsGreenLight(Context context)
|
||||
{
|
||||
return isRuleActive() && applies(context) && hasNotAppliedSinceLastExecution();
|
||||
}
|
||||
|
||||
public boolean applies(Context context)
|
||||
{
|
||||
@ -370,538 +359,8 @@ public class Rule implements Comparable<Rule>
|
||||
{
|
||||
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("<any>"))
|
||||
{
|
||||
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("<none>"))
|
||||
{
|
||||
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;
|
||||
@ -910,7 +369,21 @@ public class Rule implements Comparable<Rule>
|
||||
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not.
|
||||
* Hence it is here.
|
||||
* @param oneTrigger
|
||||
* @return
|
||||
*/
|
||||
boolean checkActivityDetection(Trigger oneTrigger)
|
||||
{
|
||||
/*
|
||||
Feature not present in FOSS edition.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
private class ActivateRuleTask extends AsyncTask<Object, String, Void>
|
||||
{
|
||||
boolean wasActivated = false;
|
||||
@ -928,7 +401,8 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
if (Looper.myLooper() == null)
|
||||
Looper.prepare();
|
||||
|
||||
|
||||
setLastExecution(Calendar.getInstance());
|
||||
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
|
||||
|
||||
return null;
|
||||
@ -953,39 +427,13 @@ public class Rule implements Comparable<Rule>
|
||||
*/
|
||||
if(wasActivated)
|
||||
{
|
||||
setLastExecution(Calendar.getInstance());
|
||||
// setLastExecution(Calendar.getInstance());
|
||||
AutomationService.updateNotification();
|
||||
ActivityMainScreen.updateMainScreen();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
||||
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,10 +444,10 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
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)
|
||||
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
|
||||
@ -1043,12 +491,12 @@ public class Rule implements Comparable<Rule>
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
return false;
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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<Rule>
|
||||
{
|
||||
@ -358,6 +334,22 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasNotAppliedSinceLastExecution()
|
||||
{
|
||||
for(Trigger oneTrigger : this.getTriggerSet())
|
||||
{
|
||||
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getsGreenLight(Context context)
|
||||
{
|
||||
return isRuleActive() && applies(context) && hasNotAppliedSinceLastExecution();
|
||||
}
|
||||
|
||||
public boolean applies(Context context)
|
||||
{
|
||||
@ -371,567 +363,8 @@ public class Rule implements Comparable<Rule>
|
||||
{
|
||||
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.activityDetection))
|
||||
{
|
||||
if(ActivityDetectionReceiver.getActivityDetectionLastResult() != null)
|
||||
{
|
||||
boolean found = false;
|
||||
for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities())
|
||||
{
|
||||
if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType())
|
||||
found = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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("<any>"))
|
||||
{
|
||||
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("<none>"))
|
||||
{
|
||||
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;
|
||||
@ -940,6 +373,44 @@ public class Rule implements Comparable<Rule>
|
||||
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not.
|
||||
* Hence it is here.
|
||||
* @param oneTrigger
|
||||
* @return
|
||||
*/
|
||||
boolean checkActivityDetection(Trigger oneTrigger)
|
||||
{
|
||||
if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null)
|
||||
{
|
||||
boolean found = false;
|
||||
for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities())
|
||||
{
|
||||
if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType())
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().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)
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class ActivateRuleTask extends AsyncTask<Object, String, Void>
|
||||
{
|
||||
@ -958,7 +429,8 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
if (Looper.myLooper() == null)
|
||||
Looper.prepare();
|
||||
|
||||
|
||||
setLastExecution(Calendar.getInstance());
|
||||
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
|
||||
|
||||
return null;
|
||||
@ -983,39 +455,13 @@ public class Rule implements Comparable<Rule>
|
||||
*/
|
||||
if(wasActivated)
|
||||
{
|
||||
setLastExecution(Calendar.getInstance());
|
||||
// setLastExecution(Calendar.getInstance());
|
||||
AutomationService.updateNotification();
|
||||
ActivityMainScreen.updateMainScreen();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
||||
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,10 +472,10 @@ public class Rule implements Comparable<Rule>
|
||||
|
||||
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)
|
||||
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
|
||||
@ -1073,12 +519,12 @@ public class Rule implements Comparable<Rule>
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
return false;
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1094,23 +1094,48 @@ public class Actions
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
WakeLock wakeLock = pm.newWakeLock((WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock");
|
||||
wakeLock.acquire();
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(awakeTime);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4);
|
||||
}
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
WakeLock wakeLock = pm.newWakeLock((WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock");
|
||||
wakeLock.acquire();
|
||||
|
||||
wakeLock.release();
|
||||
try
|
||||
{
|
||||
Thread.sleep(awakeTime);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4);
|
||||
}
|
||||
|
||||
wakeLock.release();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Wakeup device action", "Error while waking up device: " + Log.getStackTraceString(e), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void turnOnScreen()
|
||||
{
|
||||
// turn on screen
|
||||
Log.v("ProximityActivity", "ON!");
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
WakeLock wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
|
||||
wakeLock.acquire();
|
||||
}
|
||||
|
||||
@TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK
|
||||
public void turnOffScreen(){
|
||||
// turn off screen
|
||||
Log.v("ProximityActivity", "OFF!");
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
WakeLock wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "tag");
|
||||
wakeLock.acquire();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@SuppressLint("NewApi")
|
||||
public static boolean setAirplaneMode(boolean desiredState, boolean toggleActionIfPossible)
|
||||
|
@ -1375,8 +1375,7 @@ public class ActivityManageRule extends Activity
|
||||
{
|
||||
Trigger editedTrigger = new Trigger();
|
||||
editedTrigger.setTriggerType(Trigger_Enum.devicePosition);
|
||||
// newTrigger.setTriggerParameter(data.getBooleanExtra("wifiState", false));
|
||||
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageTriggerDevicePosition.vectorFieldName));
|
||||
editedTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageTriggerDevicePosition.vectorFieldName));
|
||||
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
|
||||
this.refreshTriggerList();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputFilter;
|
||||
import android.text.Spanned;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
@ -36,7 +37,7 @@ public class ActivityManageTriggerDevicePosition extends Activity
|
||||
currentPitch.setText(Float.toString(pitch));
|
||||
currentRoll.setText(Float.toString(roll));
|
||||
|
||||
if(checkInputs())
|
||||
if(checkInputs(false))
|
||||
{
|
||||
desiredAzimuth = Float.parseFloat(etDesiredAzimuth.getText().toString());
|
||||
desiredAzimuthTolerance = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString());
|
||||
@ -105,20 +106,28 @@ public class ActivityManageTriggerDevicePosition extends Activity
|
||||
// etDesiredAzimuth.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)});
|
||||
// etDesiredPitch.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)});
|
||||
// etDesiredRoll.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)});
|
||||
etDesiredAzimuthTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)});
|
||||
etDesiredPitchTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)});
|
||||
etDesiredRollTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)});
|
||||
etDesiredAzimuthTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)});
|
||||
etDesiredPitchTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)});
|
||||
etDesiredRollTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)});
|
||||
|
||||
if(getIntent().hasExtra(vectorFieldName))
|
||||
{
|
||||
editMode = true;
|
||||
String values[] = getIntent().getStringExtra(vectorFieldName).split(Trigger.triggerParameter2Split);
|
||||
etDesiredAzimuth.setText(values[0]);
|
||||
etDesiredAzimuthTolerance.setText(values[1]);
|
||||
etDesiredPitch.setText(values[2]);
|
||||
etDesiredPitchTolerance.setText(values[3]);
|
||||
etDesiredRoll.setText(values[4]);
|
||||
etDesiredRollTolerance.setText(values[5]);
|
||||
try
|
||||
{
|
||||
String values[] = getIntent().getStringExtra(vectorFieldName).split(Trigger.triggerParameter2Split);
|
||||
etDesiredAzimuth.setText(values[0]);
|
||||
etDesiredAzimuthTolerance.setText(values[1]);
|
||||
etDesiredPitch.setText(values[2]);
|
||||
etDesiredPitchTolerance.setText(values[3]);
|
||||
etDesiredRoll.setText(values[4]);
|
||||
etDesiredRollTolerance.setText(values[5]);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Toast.makeText(ActivityManageTriggerDevicePosition.this, getResources().getString(R.string.triggerWrong), Toast.LENGTH_SHORT).show();
|
||||
Miscellaneous.logEvent("e", "DevicePositionTrigger", "There\'s something wrong with a device position trigger. Content: " + getIntent().getStringExtra(vectorFieldName) + ", " + Log.getStackTraceString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
bApplyPositionValues.setOnClickListener(new View.OnClickListener()
|
||||
@ -142,7 +151,7 @@ public class ActivityManageTriggerDevicePosition extends Activity
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
if(!checkInputs())
|
||||
if(!checkInputs(true))
|
||||
{
|
||||
Toast.makeText(ActivityManageTriggerDevicePosition.this, getResources().getString(R.string.enterValidNumbersIntoAllFields), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
@ -165,7 +174,7 @@ public class ActivityManageTriggerDevicePosition extends Activity
|
||||
});
|
||||
}
|
||||
|
||||
boolean checkInputs()
|
||||
boolean checkInputs(boolean showMessages)
|
||||
{
|
||||
if(
|
||||
!StringUtils.isEmpty(etDesiredAzimuth.getText().toString()) && Miscellaneous.isNumeric(etDesiredAzimuth.getText().toString())
|
||||
@ -185,8 +194,29 @@ public class ActivityManageTriggerDevicePosition extends Activity
|
||||
float dp = Float.parseFloat(etDesiredPitch.getText().toString());
|
||||
float dr = Float.parseFloat(etDesiredRoll.getText().toString());
|
||||
|
||||
if(Math.abs(da) <= 180 || Math.abs(dp) <= 180 || Math.abs(dr) <= 180)
|
||||
return true;
|
||||
if(Math.abs(da) > 180 || Math.abs(dp) > 180 || Math.abs(dr) > 180)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(showMessages)
|
||||
{
|
||||
float dat = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString());
|
||||
float dpt = Float.parseFloat(etDesiredPitchTolerance.getText().toString());
|
||||
float drt = Float.parseFloat(etDesiredRollTolerance.getText().toString());
|
||||
|
||||
/*
|
||||
The user may enter a tolerance of 180° for two directions, but not all three.
|
||||
Otherwise this trigger would always apply.
|
||||
*/
|
||||
if (Math.abs(dat) >= 180 && Math.abs(dpt) >= 180 && Math.abs(drt) >= 180)
|
||||
{
|
||||
Miscellaneous.messageBox(getResources().getString(R.string.warning), getResources().getString(R.string.toleranceOf180OnlyAllowedIn2Fields), ActivityManageTriggerDevicePosition.this).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -264,7 +264,7 @@ public class PointOfInterest implements Comparable<PointOfInterest>
|
||||
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(parentService) && ruleCandidates.get(i).haveEnoughPermissions())
|
||||
if(ruleCandidates.get(i).haveEnoughPermissions() && ruleCandidates.get(i).getsGreenLight(parentService))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "POI", "Rule " + ruleCandidates.get(i).getName() + " applies for entering POI " + this.getName() + ".", 2);
|
||||
ruleCandidates.get(i).activate(parentService, false);
|
||||
@ -276,6 +276,7 @@ public class PointOfInterest implements Comparable<PointOfInterest>
|
||||
ActivityMainScreen.updateMainScreen();
|
||||
}
|
||||
}
|
||||
|
||||
public void deactivate(AutomationService parentService)
|
||||
{
|
||||
if(this.isActivated())
|
||||
@ -296,7 +297,7 @@ public class PointOfInterest implements Comparable<PointOfInterest>
|
||||
Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(parentService))
|
||||
if(ruleCandidates.get(i).haveEnoughPermissions() && ruleCandidates.get(i).getsGreenLight(parentService))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "POI", "Rule " + ruleCandidates.get(i).getName() + " applies for leaving POI " + this.getName() + ".", 2);
|
||||
ruleCandidates.get(i).activate(parentService, false);
|
||||
|
@ -47,6 +47,7 @@ public class ReceiverCoordinator
|
||||
BatteryReceiver.class,
|
||||
BluetoothReceiver.class,
|
||||
ConnectivityReceiver.class,
|
||||
DevicePositionListener.class,
|
||||
HeadphoneJackListener.class,
|
||||
//NfcReceiver.class,
|
||||
NoiseListener.class,
|
||||
@ -57,13 +58,12 @@ public class ReceiverCoordinator
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
// e.printStackTrace();
|
||||
|
||||
allImplementers = new Class[] {
|
||||
DateTimeListener.class,
|
||||
BatteryReceiver.class,
|
||||
BluetoothReceiver.class,
|
||||
ConnectivityReceiver.class,
|
||||
DevicePositionListener.class,
|
||||
HeadphoneJackListener.class,
|
||||
//NfcReceiver.class,
|
||||
NoiseListener.class,
|
||||
@ -167,6 +167,9 @@ public class ReceiverCoordinator
|
||||
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.process_started_stopped))
|
||||
ProcessListener.startProcessListener(AutomationService.getInstance());
|
||||
|
||||
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.devicePosition))
|
||||
DevicePositionListener.getInstance().startListener(AutomationService.getInstance());
|
||||
|
||||
try
|
||||
{
|
||||
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
|
||||
|
@ -1,83 +1,730 @@
|
||||
package com.jens.automation2;
|
||||
|
||||
import static android.content.Context.DEVICE_POLICY_SERVICE;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.jens.automation2.location.LocationProvider;
|
||||
import com.jens.automation2.location.WifiBroadcastReceiver;
|
||||
import com.jens.automation2.receivers.BatteryReceiver;
|
||||
import com.jens.automation2.receivers.BluetoothReceiver;
|
||||
import com.jens.automation2.receivers.ConnectivityReceiver;
|
||||
import com.jens.automation2.receivers.DevicePositionListener;
|
||||
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 static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT;
|
||||
import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class Trigger
|
||||
{
|
||||
Rule parentRule = null;
|
||||
boolean hasFlipped = false;
|
||||
Calendar lastTimeNotApplied = null;
|
||||
|
||||
public boolean getHasFlipped()
|
||||
{
|
||||
return hasFlipped;
|
||||
}
|
||||
|
||||
public void setHasFlipped(boolean hasFlipped)
|
||||
{
|
||||
this.hasFlipped = hasFlipped;
|
||||
}
|
||||
|
||||
public boolean applies(Object triggeringObject)
|
||||
public boolean applies(Object triggeringObject, Context context)
|
||||
{
|
||||
boolean result = true;
|
||||
|
||||
try
|
||||
{
|
||||
switch(this.getTriggerType())
|
||||
{
|
||||
case timeFrame:
|
||||
if(!checkDateTime(triggeringObject, false))
|
||||
return false;
|
||||
result = false;
|
||||
break;
|
||||
case pointOfInterest:
|
||||
if(!checkLocation())
|
||||
result = false;
|
||||
break;
|
||||
case charging:
|
||||
if(!checkCharging())
|
||||
result = false;
|
||||
break;
|
||||
case usb_host_connection:
|
||||
if(!checkUsbHostConnection())
|
||||
result = false;
|
||||
break;
|
||||
case batteryLevel:
|
||||
if(!checkBatteryLevel())
|
||||
result = false;
|
||||
break;
|
||||
case speed:
|
||||
if(!checkSpeed())
|
||||
result = false;
|
||||
break;
|
||||
case noiseLevel:
|
||||
if(!checkNoiseLevel())
|
||||
result = false;
|
||||
break;
|
||||
case wifiConnection:
|
||||
if(!checkWifiConnection())
|
||||
result = false;
|
||||
break;
|
||||
case process_started_stopped:
|
||||
if(!checkProcess())
|
||||
result = false;
|
||||
break;
|
||||
case airplaneMode:
|
||||
if(!checkAirplaneMode())
|
||||
result = false;
|
||||
break;
|
||||
case roaming:
|
||||
if(!checkRoaming())
|
||||
result = false;
|
||||
break;
|
||||
case phoneCall:
|
||||
if(!checkPhoneCall())
|
||||
result = false;
|
||||
break;
|
||||
case nfcTag:
|
||||
if(!checkNfc())
|
||||
result = false;
|
||||
break;
|
||||
case bluetoothConnection:
|
||||
if(!checkBluetooth())
|
||||
result = false;
|
||||
break;
|
||||
case headsetPlugged:
|
||||
if(!checkHeadsetPlugged())
|
||||
result = false;
|
||||
break;
|
||||
case notification:
|
||||
if(!checkNotification())
|
||||
result = false;
|
||||
break;
|
||||
case devicePosition:
|
||||
if(!checkDevicePosition())
|
||||
result = false;
|
||||
break;
|
||||
case activityDetection:
|
||||
if(!getParentRule().checkActivityDetection(this))
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1);
|
||||
return false;
|
||||
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);
|
||||
result = false;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
lastTimeNotApplied = Calendar.getInstance();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasStateRecentlyNotApplied(Object triggeringObject)
|
||||
boolean checkNotification()
|
||||
{
|
||||
// nur mit einem Trigger?
|
||||
|
||||
// door -> was state different in previous step
|
||||
|
||||
try
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
{
|
||||
switch(getTriggerType())
|
||||
String[] params = this.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(this.getTriggerParameter())
|
||||
{
|
||||
case timeFrame:
|
||||
if(!checkDateTime(triggeringObject, true))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Check an active notification that is still there
|
||||
|
||||
return true;
|
||||
boolean foundMatch = false;
|
||||
|
||||
for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications())
|
||||
{
|
||||
if(getParentRule().getLastExecution() == null || sbn.getPostTime() > this.getParentRule().getLastExecution().getTimeInMillis())
|
||||
{
|
||||
String notificationApp = sbn.getPackageName();
|
||||
String notificationTitle = null;
|
||||
String notificationText = null;
|
||||
|
||||
Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().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;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkDevicePosition()
|
||||
{
|
||||
String devicePositionPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
||||
float desiredAzimuth = Float.parseFloat(devicePositionPieces[0]);
|
||||
float desiredAzimuthTolerance = Float.parseFloat(devicePositionPieces[1]);
|
||||
float desiredPitch = Float.parseFloat(devicePositionPieces[2]);
|
||||
float desiredPitchTolerance = Float.parseFloat(devicePositionPieces[3]);
|
||||
float desiredRoll = Float.parseFloat(devicePositionPieces[4]);
|
||||
float desiredRollTolerance = Float.parseFloat(devicePositionPieces[5]);
|
||||
float currentAzimuth = DevicePositionListener.getInstance().getAzimuth();
|
||||
float currentPitch = DevicePositionListener.getInstance().getPitch();
|
||||
float currentRoll = DevicePositionListener.getInstance().getRoll();
|
||||
|
||||
if(
|
||||
desiredAzimuthTolerance < 180
|
||||
&&
|
||||
!(
|
||||
currentAzimuth <= desiredAzimuth + desiredAzimuthTolerance
|
||||
&&
|
||||
currentAzimuth >= desiredAzimuth - desiredAzimuthTolerance
|
||||
)
|
||||
)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1);
|
||||
Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Azimuth outside of tolerance area.", 5);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(
|
||||
desiredPitchTolerance < 180
|
||||
&&
|
||||
!(
|
||||
currentPitch <= desiredPitch + desiredPitchTolerance
|
||||
&&
|
||||
currentPitch >= desiredPitch - desiredPitchTolerance
|
||||
)
|
||||
)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Pitch outside of tolerance area.", 5);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(
|
||||
desiredRollTolerance < 180
|
||||
&&
|
||||
!(
|
||||
currentRoll <= desiredRoll + desiredRollTolerance
|
||||
&&
|
||||
currentRoll >= desiredRoll - desiredRollTolerance
|
||||
)
|
||||
)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Roll outside of tolerance area.", 5);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkHeadsetPlugged()
|
||||
{
|
||||
if(HeadphoneJackListener.isHeadsetConnected() != this.getTriggerParameter())
|
||||
return false;
|
||||
else
|
||||
if(this.getHeadphoneType() != 2 && this.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkBluetooth()
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Checking for bluetooth...", 4);
|
||||
|
||||
if(this.getBluetoothDeviceAddress().equals("<any>"))
|
||||
{
|
||||
if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED))
|
||||
{
|
||||
if(BluetoothReceiver.isAnyDeviceConnected() != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)))
|
||||
{
|
||||
if(BluetoothReceiver.isAnyDeviceConnected() != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// range
|
||||
if(BluetoothReceiver.isAnyDeviceInRange() != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(this.getBluetoothDeviceAddress().equals("<none>"))
|
||||
{
|
||||
if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED))
|
||||
{
|
||||
if(BluetoothReceiver.isAnyDeviceConnected() == this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)))
|
||||
{
|
||||
if(BluetoothReceiver.isAnyDeviceConnected() == this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// range
|
||||
if(BluetoothReceiver.isAnyDeviceInRange() == this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(this.getBluetoothDeviceAddress().length() > 0)
|
||||
{
|
||||
if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED))
|
||||
{
|
||||
if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)))
|
||||
{
|
||||
if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// range
|
||||
if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkNfc()
|
||||
{
|
||||
if(NfcReceiver.lastReadLabel == null)
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3);
|
||||
return false;
|
||||
}
|
||||
else if(!NfcReceiver.lastReadLabel.equals(this.getNfcTagId()))
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + this.getNfcTagId(), 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkPhoneCall()
|
||||
{
|
||||
String[] elements = this.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", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong direction. Demanded: " + String.valueOf(this.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Rule", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong call status. Demanded: " + String.valueOf(this.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Rule", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong phone number. Demanded: " + this.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean checkRoaming()
|
||||
{
|
||||
if(ConnectivityReceiver.isRoaming(Miscellaneous.getAnyContext()) != this.getTriggerParameter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkAirplaneMode()
|
||||
{
|
||||
if(ConnectivityReceiver.isAirplaneMode(Miscellaneous.getAnyContext()) != this.getTriggerParameter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkProcess()
|
||||
{
|
||||
boolean running = ProcessListener.getRunningApps().contains(this.getProcessName());
|
||||
|
||||
if(running)
|
||||
Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is currently running.", 4);
|
||||
else
|
||||
Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is not running.", 4);
|
||||
|
||||
if(running != this.getTriggerParameter())
|
||||
{
|
||||
Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4);
|
||||
return false;
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkWifiConnection()
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Checking for wifi state", 4);
|
||||
if(this.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected
|
||||
{
|
||||
if(this.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi name specified, checking that.", 4);
|
||||
if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2()))
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi name matches. Rule will apply.", 4);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "No wifi name specified, any will do.", 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi state not correct, demanded " + String.valueOf(this.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkNoiseLevel()
|
||||
{
|
||||
if(this.getTriggerParameter())
|
||||
{
|
||||
if(NoiseListener.getNoiseLevelDb() < this.getNoiseLevelDb())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(this.getNoiseLevelDb()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(NoiseListener.getNoiseLevelDb() > this.getNoiseLevelDb())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(this.getNoiseLevelDb()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkSpeed()
|
||||
{
|
||||
if(this.getTriggerParameter())
|
||||
{
|
||||
if(LocationProvider.getSpeed() < this.getSpeed())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(this.getSpeed()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(LocationProvider.getSpeed() > this.getSpeed())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(this.getSpeed()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkBatteryLevel()
|
||||
{
|
||||
if(this.getTriggerParameter())
|
||||
{
|
||||
if(BatteryReceiver.getBatteryLevel() <= this.getBatteryLevel())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(this.getBatteryLevel()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(this.getBatteryLevel() >= this.getBatteryLevel())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(this.getBatteryLevel()), 3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkUsbHostConnection()
|
||||
{
|
||||
if(BatteryReceiver.isUsbHostConnected() != this.getTriggerParameter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkLocation()
|
||||
{
|
||||
// Am I here?
|
||||
PointOfInterest activePoi = PointOfInterest.getActivePoi();
|
||||
if(activePoi != null) //entering one
|
||||
{
|
||||
if(this.getPointOfInterest() != null)
|
||||
{
|
||||
if(activePoi.equals(this.getPointOfInterest()))
|
||||
{
|
||||
if(!this.getTriggerParameter())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're entering POI: " + this.getPointOfInterest().getName() + ", not leaving it.", 4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + this.getPointOfInterest().getName() + ".", 4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(this.getPointOfInterest() == null)
|
||||
{
|
||||
if(this.getTriggerParameter())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().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(this.getPointOfInterest() != null)
|
||||
{
|
||||
// if(activePoi.equals(oneTrigger.getPointOfInterest()))
|
||||
// {
|
||||
if(!this.getTriggerParameter())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "We are not at POI \"" + this.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", 3);
|
||||
return false;
|
||||
}
|
||||
// }
|
||||
}
|
||||
else if(this.getPointOfInterest() == null)
|
||||
{
|
||||
if(!this.getTriggerParameter())
|
||||
{
|
||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasStateNotAppliedSinceLastRuleExecution()
|
||||
{
|
||||
if(getParentRule().getLastExecution() == null)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " has NOT applied since the parent rule\'s last activation.", 4);
|
||||
return true;
|
||||
}
|
||||
else if(lastTimeNotApplied != null)
|
||||
{
|
||||
if(lastTimeNotApplied.getTimeInMillis() > getParentRule().getLastExecution().getTimeInMillis())
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " has NOT applied since the parent rule\'s last activation.", 4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " may apply currently, but has not NOT applied since the rule\'s last execution.", 4);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean checkCharging()
|
||||
{
|
||||
if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0)
|
||||
{
|
||||
return false; // unknown charging state, can't activate rule under these conditions
|
||||
}
|
||||
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1)
|
||||
{
|
||||
if(this.getTriggerParameter()) //rule says when charging, but we're currently discharging
|
||||
return false;
|
||||
}
|
||||
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2)
|
||||
{
|
||||
if(!this.getTriggerParameter()) //rule says when discharging, but we're currently charging
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution)
|
||||
@ -754,21 +1401,25 @@ public class Trigger
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
device = Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice);
|
||||
Miscellaneous.logEvent("w", "Trigger", Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice), 3);
|
||||
device = Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice) + ": " + device;
|
||||
Miscellaneous.logEvent("w", "Trigger", Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice) + ": " + device, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if(bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_CONNECTED) | bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))
|
||||
if(this.triggerParameter)
|
||||
if(bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_CONNECTED) || bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))
|
||||
{
|
||||
if (this.triggerParameter)
|
||||
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothConnectionTo), device));
|
||||
else
|
||||
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDisconnectFrom), device));
|
||||
}
|
||||
else if(bluetoothEvent.equals(BluetoothDevice.ACTION_FOUND))
|
||||
if(this.triggerParameter)
|
||||
{
|
||||
if (this.triggerParameter)
|
||||
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDeviceInRange), device));
|
||||
else
|
||||
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDeviceOutOfRange), device));
|
||||
}
|
||||
// }
|
||||
break;
|
||||
case headsetPlugged:
|
||||
|
@ -201,7 +201,7 @@ public class LocationProvider
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesBySpeed();
|
||||
for (Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if (oneRule.applies(this.getParentService()))
|
||||
if(oneRule.getsGreenLight(this.getParentService()))
|
||||
oneRule.activate(getParentService(), false);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByWifiConnection();
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(automationServiceInstance))
|
||||
if(oneRule.getsGreenLight(automationServiceInstance))
|
||||
oneRule.activate(automationServiceInstance, false);
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
if(ruleCandidates.get(i).getsGreenLight(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
@ -219,7 +219,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByBatteryLevel();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
if(ruleCandidates.get(i).getsGreenLight(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
@ -234,7 +234,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(false);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
if(ruleCandidates.get(i).getsGreenLight(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
@ -257,7 +257,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(true);
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(context))
|
||||
if(oneRule.getsGreenLight(context))
|
||||
oneRule.activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(false);
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(context))
|
||||
if(oneRule.getsGreenLight(context))
|
||||
oneRule.activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(AutomationService.getInstance()))
|
||||
if(ruleCandidates.get(i).getsGreenLight(AutomationService.getInstance()))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public class ConnectivityReceiver extends BroadcastReceiver implements Automatio
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationServiceRef))
|
||||
if(ruleCandidates.get(i).getsGreenLight(automationServiceRef))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,7 @@ public class ConnectivityReceiver extends BroadcastReceiver implements Automatio
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationServiceRef))
|
||||
if(ruleCandidates.get(i).getsGreenLight(automationServiceRef))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
||||
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime);
|
||||
for(int i=0; i<allRulesWithNowInTimeFrame.size(); i++)
|
||||
{
|
||||
if(allRulesWithNowInTimeFrame.get(i).applies(context))
|
||||
if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context))
|
||||
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
||||
|
||||
if(tf.getRepetition() > 0)
|
||||
{
|
||||
if(oneTrigger.applies(calNow))
|
||||
if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext()))
|
||||
{
|
||||
Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow);
|
||||
|
||||
|
@ -41,6 +41,11 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi
|
||||
private float pitch;
|
||||
private float roll;
|
||||
|
||||
boolean applies = false;
|
||||
boolean flipped = false;
|
||||
boolean toggable = false;
|
||||
|
||||
|
||||
public static DevicePositionListener getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
@ -49,6 +54,21 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi
|
||||
return instance;
|
||||
}
|
||||
|
||||
public float getAzimuth()
|
||||
{
|
||||
return azimuth;
|
||||
}
|
||||
|
||||
public float getPitch()
|
||||
{
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getRoll()
|
||||
{
|
||||
return roll;
|
||||
}
|
||||
|
||||
public void startSensorFromConfigActivity(Context context, ActivityManageTriggerDevicePosition activityManageTriggerDevicePositionInstance)
|
||||
{
|
||||
this.activityManageTriggerDevicePositionInstance = activityManageTriggerDevicePositionInstance;
|
||||
@ -72,6 +92,8 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi
|
||||
|
||||
public void stopSensorFromConfigActivity()
|
||||
{
|
||||
activityManageTriggerDevicePositionInstance = null;
|
||||
|
||||
if(isRunning)
|
||||
{
|
||||
if(!Rule.isAnyRuleUsing(Trigger.Trigger_Enum.devicePosition))
|
||||
@ -127,7 +149,7 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi
|
||||
ArrayList<Rule> 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).getsGreenLight(Miscellaneous.getAnyContext()))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected());
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
if(ruleCandidates.get(i).getsGreenLight(context))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class NfcReceiver
|
||||
ArrayList<Rule> allRulesWithNfcTags = Rule.findRuleCandidatesByNfc();
|
||||
for(int i=0; i<allRulesWithNfcTags.size(); i++)
|
||||
{
|
||||
if(allRulesWithNfcTags.get(i).applies(asInstance))
|
||||
if(allRulesWithNfcTags.get(i).getsGreenLight(asInstance))
|
||||
allRulesWithNfcTags.get(i).activate(asInstance, false);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class NoiseListener implements AutomationListenerInterface
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByNoiseLevel();
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(automationService))
|
||||
if(oneRule.getsGreenLight(automationService))
|
||||
oneRule.activate(automationService, false);
|
||||
}
|
||||
}
|
||||
|
@ -89,19 +89,12 @@ public class NotificationListener extends NotificationListenerService
|
||||
lastNotification.title = title;
|
||||
lastNotification.text = text;
|
||||
|
||||
// if(lastResponseToNotification == null || lastResponseToNotification.getTimeInMillis() < lastNotification.publishTime.getTimeInMillis())
|
||||
// {
|
||||
// lastResponseToNotification = Calendar.getInstance();
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification);
|
||||
for (int i = 0; i < ruleCandidates.size(); i++)
|
||||
{
|
||||
if (ruleCandidates.get(i).applies(NotificationListener.this))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// Miscellaneous.logEvent("e", "NotificationCheck", "Ignoring notification as it is old.", 5);
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification);
|
||||
for (int i = 0; i < ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).getsGreenLight(NotificationListener.this))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -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).getsGreenLight(asInstance))
|
||||
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).getsGreenLight(asInstance))
|
||||
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).getsGreenLight(asInstance))
|
||||
ruleCandidates.get(i).activate(asInstance, false);
|
||||
}
|
||||
}
|
||||
|
@ -43,34 +43,27 @@ public class ProcessListener implements AutomationListenerInterface
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.messageReceivedStatingProcessMonitoringIsComplete), 5);
|
||||
// This will take care of results delivered by the actual monitoring instance
|
||||
|
||||
for(String entry : getRunningApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.runningApp), entry, 5);
|
||||
|
||||
// execute matching rules containing processes
|
||||
if(getRecentlyStartedApps().size()>0 | getRecentlyStoppedApps().size()>0)
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.messageReceivedStatingProcessMonitoringIsComplete), 5);
|
||||
// This will take care of results delivered by the actual monitoring instance
|
||||
|
||||
for(String entry : getRunningApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.runningApp), entry, 5);
|
||||
|
||||
// execute matching rules containing processes
|
||||
if(getRecentlyStartedApps().size()>0 | getRecentlyStoppedApps().size()>0)
|
||||
{
|
||||
for(String entry : getRecentlyStartedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStarted), entry, 3);
|
||||
for(String entry : getRecentlyStoppedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStopped), entry, 3);
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByProcess();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
for(String entry : getRecentlyStartedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStarted), entry, 3);
|
||||
for(String entry : getRecentlyStoppedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStopped), entry, 3);
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByProcess();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationService))
|
||||
ruleCandidates.get(i).activate(automationService, false);
|
||||
}
|
||||
if(ruleCandidates.get(i).getsGreenLight(automationService))
|
||||
ruleCandidates.get(i).activate(automationService, false);
|
||||
}
|
||||
// }
|
||||
// catch(Exception e)
|
||||
// {
|
||||
// Miscellaneous.logEvent("e", "Noise level", "Error in workHandler->handleMessage(): " + e.getMessage());
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -97,13 +97,14 @@
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:text="Position"
|
||||
android:text="@string/position"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:text="@string/tolerance"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
@ -146,6 +147,8 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAppliesAzimuth"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/unknown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
@ -178,6 +181,8 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAppliesPitch"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/unknown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
@ -210,6 +215,8 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAppliesRoll"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/unknown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
@ -212,15 +212,15 @@
|
||||
<string name="wifiName">Wifi name</string>
|
||||
<string name="enterWifiName">Enter a wifi name. Leave empty for any wifi.</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="ruleDoesntApplyWeAreSlowerThan" translatable="false">Rule doesn\'t apply. We are slower than</string>
|
||||
<string name="ruleDoesntApplyWeAreFasterThan" translatable="false">Rule doesn\'t apply. We are faster than</string>
|
||||
<string name="ruleDoesntApplyItsQuieterThan" translatable="false">Rule doesn\'t apply. It\'s quieter than</string>
|
||||
<string name="ruleDoesntApplyItsLouderThan" translatable="false">Rule doesn\'t apply. It\'s louder than</string>
|
||||
<string name="ruleDoesntApplyBatteryLowerThan" translatable="false">Rule doesn\'t apply. Battery level is lower than</string>
|
||||
<string name="ruleDoesntApplyBatteryHigherThan" translatable="false">Rule doesn\'t apply. Battery level is higher than</string>
|
||||
<string name="ruleDoesntApplyNotTheCorrectSsid" translatable="false">Rule doesn\'t apply. Not the correct SSID (demanded: \"%1$s\", given: \"%2$s\").</string>
|
||||
<string name="ruleDoesntApplyNoTagLabel" translatable="false">Rule doesn\'t apply. There is no tag label or not tag at all.</string>
|
||||
<string name="ruleDoesntApplyWrongTagLabel" translatable="false">Rule doesn\'t apply. Wrong tag label.</string>
|
||||
<string name="ruleDoesntApplyWeAreSlowerThan" translatable="false">Rule %1$s doesn\'t apply. We are slower than</string>
|
||||
<string name="ruleDoesntApplyWeAreFasterThan" translatable="false">Rule %1$s doesn\'t apply. We are faster than</string>
|
||||
<string name="ruleDoesntApplyItsQuieterThan" translatable="false">Rule %1$s doesn\'t apply. It\'s quieter than</string>
|
||||
<string name="ruleDoesntApplyItsLouderThan" translatable="false">Rule %1$s doesn\'t apply. It\'s louder than</string>
|
||||
<string name="ruleDoesntApplyBatteryLowerThan" translatable="false">Rule %1$s doesn\'t apply. Battery level is lower than</string>
|
||||
<string name="ruleDoesntApplyBatteryHigherThan" translatable="false">Rule %1$s doesn\'t apply. Battery level is higher than</string>
|
||||
<string name="ruleDoesntApplyNotTheCorrectSsid" translatable="false">Rule %1$s doesn\'t apply. Not the correct SSID (demanded: \"%2$s\", given: \"%3$s\").</string>
|
||||
<string name="ruleDoesntApplyNoTagLabel" translatable="false">Rule %1$s doesn\'t apply. There is no tag label or not tag at all.</string>
|
||||
<string name="ruleDoesntApplyWrongTagLabel" translatable="false">Rule %1$s doesn\'t apply. Wrong tag label.</string>
|
||||
<string name="ruleIsDeactivatedCantApply" translatable="false">Rule %1$s is deactivated, can\'t apply.</string>
|
||||
<string name="starting">starting</string>
|
||||
<string name="stopping">stopping</string>
|
||||
@ -714,12 +714,16 @@
|
||||
<string name="btTetheringNotice">This feature is confirmed to work up until Android 8.0. From some higher version upwards it ceases to work, but due to a lack of physical devices I cannot tell which one that is. On Android 11 it definitely ain\'t working anymore. If you have a version in between please let me know if it\'s working or not.</string>
|
||||
<string name="notice">Notice</string>
|
||||
<string name="devicePosition">Device position (Gyroscope)</string>
|
||||
<string name="tolerance">Tolerance</string>
|
||||
<string name="tolerance">Tolerance\n(0-180)</string>
|
||||
<string name="orientationAzimuth">Azimuth:</string>
|
||||
<string name="orientationPitch">Pitch:</string>
|
||||
<string name="orientationRoll">Roll:</string>
|
||||
<string name="enterValidNumbersIntoAllFields">Enter valid numbers in all fields.</string>
|
||||
<string name="devicePositionExplanation">When you move your device the below numbers should update. What you can see there, is the current \"position\" of your device. If it is in the desired position, click the apply button to copy the current values to the desired fields.\nBecause you will probably not be able to reach this exact position ever again, enter a tolerance. The is amount to which the position can deviate in one direction or the other.</string>
|
||||
<string name="devicePositionExplanation">When you move your device the below numbers will update. What you can see there, is the current \"position\" of your device measured in degrees. If it is in the desired position, click the apply button to copy the current values to the desired fields.\nBecause reaching this exact position ever again is highly unlikely you must also enter a tolerance. The is amount of degrees to which the position can deviate in either direction. If you only care about one specific axis, specify a tolerance of 180° for the two other ones.</string>
|
||||
<string name="wouldCurrentlyApply">Would currently apply?</string>
|
||||
<string name="deviceIsInCertainPosition">the device is in a certain position</string>
|
||||
<string name="toleranceOf180OnlyAllowedIn2Fields">A tolerance of 180 is allowed for 2 tolerance fields only, not all 3. Otherwise the trigger would ALWAYS apply.</string>
|
||||
<string name="unknown">unknown</string>
|
||||
<string name="position">Position</string>
|
||||
<string name="triggerWrong">" There's something wrong with this trigger. It could not be loaded correctly."</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user