24 Commits

Author SHA1 Message Date
7046cccabe new release prep 2022-05-15 01:37:18 +02:00
bdbed3dbef app info text updated 2022-05-10 12:42:14 +02:00
3f36c4c6b3 bug when picking app to start 2022-05-09 20:09:11 +02:00
52a10fe626 bug when importing config while service is not running 2022-05-08 20:04:45 +02:00
9fce7d987e bug when importing config while service is not running 2022-05-08 14:50:40 +02:00
d5ce04f80b wifi trigger, memorize most recent ssid 2022-05-07 02:06:17 +02:00
62c97832a9 fix in DateTimeTrigger management and executions when service already stopped 2022-04-04 20:21:34 +02:00
391edc59bf fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 20:25:10 +02:00
0d3a13e753 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 16:20:20 +02:00
152b0c3c49 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 14:46:28 +02:00
7ed04c7ae2 cosmetics 2022-03-29 17:56:04 +02:00
c688a4c460 TimeFrame repetition fix 2022-03-26 20:00:50 +01:00
5a09962cc9 TimeFrame repetition fix 2022-03-26 20:00:19 +01:00
0368b2a8c8 v118 2022-03-13 16:06:10 +01:00
217f459833 nfc fix 2022-03-05 20:59:16 +01:00
4c9e61618b profile delete bug fixed 2022-02-28 13:46:18 +01:00
e719114166 parallel rule execution 2022-02-27 18:01:54 +01:00
0bd64e4a53 operator change 2022-02-22 23:08:25 +01:00
c569ab798c Android 11 2022-02-22 22:15:27 +01:00
4e46878009 wrong field changed 2022-02-22 17:55:43 +01:00
72ccdd99f9 logging 2022-02-20 18:57:13 +01:00
c9d7399068 logging 2022-02-14 20:06:20 +01:00
275091f9d7 libs 2022-02-06 15:02:07 +01:00
bc31c9a4c8 translation 2022-02-05 13:47:43 +01:00
40 changed files with 473 additions and 366 deletions

View File

@ -11,8 +11,8 @@ android {
compileSdkVersion 31 compileSdkVersion 31
buildToolsVersion '29.0.2' buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy' useLibrary 'org.apache.http.legacy'
versionCode 118 versionCode 119
versionName "1.7.4" versionName "1.7.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -28,10 +28,6 @@ android {
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
lintOptions {
checkReleaseBuilds false
abortOnError false
}
flavorDimensions "version" flavorDimensions "version"
@ -57,6 +53,10 @@ android {
targetSdkVersion 28 targetSdkVersion 28
} }
} }
lint {
abortOnError false
checkReleaseBuilds false
}
} }
dependencies { dependencies {

View File

@ -11,8 +11,8 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 116, "versionCode": 119,
"versionName": "1.7.2-googlePlay", "versionName": "1.7.5-googlePlay",
"outputFile": "app-googlePlayFlavor-release.apk" "outputFile": "app-googlePlayFlavor-release.apk"
} }
], ],

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -20,24 +21,23 @@ import java.util.List;
public class Rule implements Comparable<Rule> public class Rule implements Comparable<Rule>
{ {
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>(); protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory() public static List<Rule> getRuleRunHistory()
{ {
return ruleRunHistory; return ruleRunHistory;
} }
private ArrayList<Trigger> triggerSet; protected ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet; protected ArrayList<Action> actionSet;
private String name; protected String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution; protected Calendar lastExecution;
private static Date lastActivatedRuleActivationTime; protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution() public Calendar getLastExecution()
{ {
@ -185,6 +185,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true)) if(this.checkBeforeSaving(context, true))
{ {
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3); Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile(); boolean returnValue = XmlFileInterface.writeFile();
if(returnValue) if(returnValue)
@ -233,20 +234,24 @@ public class Rule implements Comparable<Rule>
} }
if(!changeExistingRule) if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection) {
if(rule.getName().equals(this.getName())) for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{ {
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false; return false;
} }
}
if(this.getTriggerSet().size()==0) }
if(this.getTriggerSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false; return false;
} }
if(this.getActionSet().size()==0) if(this.getActionSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false; return false;
@ -312,19 +317,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction()) switch(action.getAction())
{ {
case setAirplaneMode: case setAirplaneMode:
return true;
case setBluetooth: case setBluetooth:
return true;
case setDataConnection: case setDataConnection:
return true;
case setDisplayRotation: case setDisplayRotation:
return true;
case setUsbTethering: case setUsbTethering:
return true;
case setWifi: case setWifi:
return true;
case setWifiTethering: case setWifiTethering:
return true;
case setBluetoothTethering: case setBluetoothTethering:
return true; return true;
default: default:
@ -341,6 +339,15 @@ public class Rule implements Comparable<Rule>
{ {
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true; return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
} }
return false; return false;
@ -351,7 +358,10 @@ public class Rule implements Comparable<Rule>
if(applies(context)) if(applies(context))
{ {
if(hasNotAppliedSinceLastExecution()) if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true; return true;
}
else else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4); Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
} }
@ -433,7 +443,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler); Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class // without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected()) if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger(); android.os.Debug.waitForDebugger();
@ -441,7 +451,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare(); Looper.prepare();
setLastExecution(Calendar.getInstance()); setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); wasActivated = activateInternally((AutomationService)params[0]);
return null; return null;
} }
@ -476,66 +486,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread * Will activate the rule. Should be called by a separate execution thread
* @param automationService * @param automationService
*/ */
protected boolean activateInternally(AutomationService automationService, boolean force) protected boolean activateInternally(AutomationService automationService)
{ {
boolean isActuallyToggable = isActuallyToggable(); boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable; boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle) String message;
// if(force || doToggle) if(!doToggle)
// { message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
String message; else
if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++) Miscellaneous.logEvent("i", "Rule", message, 2);
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
// Keep log of last x rule activations (Settings) if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try try
{ {
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization Rule.this.getActionSet().get(i).run(automationService, doToggle);
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
} }
catch(Exception e) catch(Exception e)
{ {
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
} }
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); // Keep log of last x rule activations (Settings)
// } try
// else {
// { Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
// 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); Rule.lastActivatedRuleActivationTime = new Date();
// return false;
// } while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true; return true;
} }
@ -544,7 +545,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force) public void activate(AutomationService automationService, boolean force)
{ {
ActivateRuleTask task = new ActivateRuleTask(); ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
} }
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType) public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@ -553,13 +557,13 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection) for(Rule oneRule : ruleCollection)
{ {
innerloop: innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet()) for(Trigger oneTrigger : oneRule.getTriggerSet())
{ {
if(oneTrigger.getTriggerType().equals(triggerType)) if(oneTrigger.getTriggerType().equals(triggerType))
{ {
ruleCandidates.add(oneRule); ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule break innerLoop; // we don't need to check the other triggers in the same rule
} }
} }
} }

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -17,24 +18,23 @@ import java.util.List;
public class Rule implements Comparable<Rule> public class Rule implements Comparable<Rule>
{ {
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>(); protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory() public static List<Rule> getRuleRunHistory()
{ {
return ruleRunHistory; return ruleRunHistory;
} }
private ArrayList<Trigger> triggerSet; protected ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet; protected ArrayList<Action> actionSet;
private String name; protected String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution; protected Calendar lastExecution;
private static Date lastActivatedRuleActivationTime; protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution() public Calendar getLastExecution()
{ {
@ -182,6 +182,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true)) if(this.checkBeforeSaving(context, true))
{ {
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3); Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile(); boolean returnValue = XmlFileInterface.writeFile();
if(returnValue) if(returnValue)
@ -230,20 +231,24 @@ public class Rule implements Comparable<Rule>
} }
if(!changeExistingRule) if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection) {
if(rule.getName().equals(this.getName())) for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{ {
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false; return false;
} }
}
if(this.getTriggerSet().size()==0) }
if(this.getTriggerSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false; return false;
} }
if(this.getActionSet().size()==0) if(this.getActionSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false; return false;
@ -309,19 +314,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction()) switch(action.getAction())
{ {
case setAirplaneMode: case setAirplaneMode:
return true;
case setBluetooth: case setBluetooth:
return true;
case setDataConnection: case setDataConnection:
return true;
case setDisplayRotation: case setDisplayRotation:
return true;
case setUsbTethering: case setUsbTethering:
return true;
case setWifi: case setWifi:
return true;
case setWifiTethering: case setWifiTethering:
return true;
case setBluetoothTethering: case setBluetoothTethering:
return true; return true;
default: default:
@ -338,6 +336,15 @@ public class Rule implements Comparable<Rule>
{ {
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true; return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
} }
return false; return false;
@ -348,7 +355,10 @@ public class Rule implements Comparable<Rule>
if(applies(context)) if(applies(context))
{ {
if(hasNotAppliedSinceLastExecution()) if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true; return true;
}
else else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4); Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
} }
@ -406,7 +416,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler); Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class // without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected()) if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger(); android.os.Debug.waitForDebugger();
@ -414,7 +424,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare(); Looper.prepare();
setLastExecution(Calendar.getInstance()); setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); wasActivated = activateInternally((AutomationService)params[0]);
return null; return null;
} }
@ -449,66 +459,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread * Will activate the rule. Should be called by a separate execution thread
* @param automationService * @param automationService
*/ */
protected boolean activateInternally(AutomationService automationService, boolean force) protected boolean activateInternally(AutomationService automationService)
{ {
boolean isActuallyToggable = isActuallyToggable(); boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable; boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle) String message;
// if(force || doToggle) if(!doToggle)
// { message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
String message; else
if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++) Miscellaneous.logEvent("i", "Rule", message, 2);
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
// Keep log of last x rule activations (Settings) if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try try
{ {
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization Rule.this.getActionSet().get(i).run(automationService, doToggle);
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
} }
catch(Exception e) catch(Exception e)
{ {
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
} }
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); // Keep log of last x rule activations (Settings)
// } try
// else {
// { Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
// 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); Rule.lastActivatedRuleActivationTime = new Date();
// return false;
// } while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true; return true;
} }
@ -517,7 +518,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force) public void activate(AutomationService automationService, boolean force)
{ {
ActivateRuleTask task = new ActivateRuleTask(); ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
} }
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType) public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@ -526,13 +530,13 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection) for(Rule oneRule : ruleCollection)
{ {
innerloop: innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet()) for(Trigger oneTrigger : oneRule.getTriggerSet())
{ {
if(oneTrigger.getTriggerType().equals(triggerType)) if(oneTrigger.getTriggerType().equals(triggerType))
{ {
ruleCandidates.add(oneRule); ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule break innerLoop; // we don't need to check the other triggers in the same rule
} }
} }
} }

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -20,24 +21,23 @@ import java.util.List;
public class Rule implements Comparable<Rule> public class Rule implements Comparable<Rule>
{ {
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>(); protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory() public static List<Rule> getRuleRunHistory()
{ {
return ruleRunHistory; return ruleRunHistory;
} }
private ArrayList<Trigger> triggerSet; protected ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet; protected ArrayList<Action> actionSet;
private String name; protected String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution; protected Calendar lastExecution;
private static Date lastActivatedRuleActivationTime; protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution() public Calendar getLastExecution()
{ {
@ -185,6 +185,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true)) if(this.checkBeforeSaving(context, true))
{ {
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3); Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile(); boolean returnValue = XmlFileInterface.writeFile();
if(returnValue) if(returnValue)
@ -233,20 +234,24 @@ public class Rule implements Comparable<Rule>
} }
if(!changeExistingRule) if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection) {
if(rule.getName().equals(this.getName())) for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{ {
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false; return false;
} }
}
if(this.getTriggerSet().size()==0) }
if(this.getTriggerSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false; return false;
} }
if(this.getActionSet().size()==0) if(this.getActionSet().size() == 0)
{ {
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false; return false;
@ -312,19 +317,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction()) switch(action.getAction())
{ {
case setAirplaneMode: case setAirplaneMode:
return true;
case setBluetooth: case setBluetooth:
return true;
case setDataConnection: case setDataConnection:
return true;
case setDisplayRotation: case setDisplayRotation:
return true;
case setUsbTethering: case setUsbTethering:
return true;
case setWifi: case setWifi:
return true;
case setWifiTethering: case setWifiTethering:
return true;
case setBluetoothTethering: case setBluetoothTethering:
return true; return true;
default: default:
@ -341,6 +339,15 @@ public class Rule implements Comparable<Rule>
{ {
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true; return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
} }
return false; return false;
@ -351,7 +358,10 @@ public class Rule implements Comparable<Rule>
if(applies(context)) if(applies(context))
{ {
if(hasNotAppliedSinceLastExecution()) if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true; return true;
}
else else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4); Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
} }
@ -433,7 +443,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler); Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class // without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected()) if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger(); android.os.Debug.waitForDebugger();
@ -441,7 +451,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare(); Looper.prepare();
setLastExecution(Calendar.getInstance()); setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); wasActivated = activateInternally((AutomationService)params[0]);
return null; return null;
} }
@ -476,66 +486,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread * Will activate the rule. Should be called by a separate execution thread
* @param automationService * @param automationService
*/ */
protected boolean activateInternally(AutomationService automationService, boolean force) protected boolean activateInternally(AutomationService automationService)
{ {
boolean isActuallyToggable = isActuallyToggable(); boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable; boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle) String message;
// if(force || doToggle) if(!doToggle)
// { message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
String message; else
if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++) Miscellaneous.logEvent("i", "Rule", message, 2);
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
// Keep log of last x rule activations (Settings) if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try try
{ {
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization Rule.this.getActionSet().get(i).run(automationService, doToggle);
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
} }
catch(Exception e) catch(Exception e)
{ {
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
} }
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); // Keep log of last x rule activations (Settings)
// } try
// else {
// { Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
// 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); Rule.lastActivatedRuleActivationTime = new Date();
// return false;
// } while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true; return true;
} }
@ -544,7 +545,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force) public void activate(AutomationService automationService, boolean force)
{ {
ActivateRuleTask task = new ActivateRuleTask(); ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
} }
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType) public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@ -553,13 +557,13 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection) for(Rule oneRule : ruleCollection)
{ {
innerloop: innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet()) for(Trigger oneTrigger : oneRule.getTriggerSet())
{ {
if(oneTrigger.getTriggerType().equals(triggerType)) if(oneTrigger.getTriggerType().equals(triggerType))
{ {
ruleCandidates.add(oneRule); ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule break innerLoop; // we don't need to check the other triggers in the same rule
} }
} }
} }

View File

@ -222,6 +222,10 @@ public class ActivityControlCenter extends Activity
} }
Settings.readFromPersistentStorage(ActivityControlCenter.this); Settings.readFromPersistentStorage(ActivityControlCenter.this);
AutomationService service = AutomationService.getInstance();
if(service != null && service.isRunning)
service.applySettingsAndRules();
} }
else else
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show(); Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
@ -342,13 +346,16 @@ public class ActivityControlCenter extends Activity
public static String getSystemInfo() public static String getSystemInfo()
{ {
StringBuilder systemInfoText = new StringBuilder(); StringBuilder systemInfoText = new StringBuilder();
systemInfoText.append("App details" + Miscellaneous.lineSeparator);
systemInfoText.append("Version name: " + BuildConfig.VERSION_NAME + Miscellaneous.lineSeparator);
systemInfoText.append("Version code: " + BuildConfig.VERSION_CODE + Miscellaneous.lineSeparator);
systemInfoText.append("Flavor: " + BuildConfig.FLAVOR + Miscellaneous.lineSeparator);
systemInfoText.append("Device details" + Miscellaneous.lineSeparator); systemInfoText.append("Device details" + Miscellaneous.lineSeparator);
systemInfoText.append("OS version: " + System.getProperty("os.version") + Miscellaneous.lineSeparator); systemInfoText.append("OS version: " + System.getProperty("os.version") + Miscellaneous.lineSeparator);
systemInfoText.append("API Level: " + android.os.Build.VERSION.SDK + Miscellaneous.lineSeparator); systemInfoText.append("API Level: " + android.os.Build.VERSION.SDK + Miscellaneous.lineSeparator);
systemInfoText.append("Device: " + android.os.Build.DEVICE + Miscellaneous.lineSeparator); systemInfoText.append("Device: " + android.os.Build.DEVICE + Miscellaneous.lineSeparator);
systemInfoText.append("Model: " + android.os.Build.MODEL + Miscellaneous.lineSeparator); systemInfoText.append("Model: " + android.os.Build.MODEL + Miscellaneous.lineSeparator);
systemInfoText.append("Product: " + android.os.Build.PRODUCT + Miscellaneous.lineSeparator); systemInfoText.append("Product: " + android.os.Build.PRODUCT + Miscellaneous.lineSeparator);
systemInfoText.append("Flavor: " + BuildConfig.FLAVOR + Miscellaneous.lineSeparator);
systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator); systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator);
systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName()); systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName());

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
public class ActivityMainRules extends ActivityGeneric public class ActivityMainRules extends ActivityGeneric
{ {
public static final String intentNameRuleName = "ruleName";
private ListView ruleListView; private ListView ruleListView;
ArrayList<Rule> ruleList = new ArrayList<>(); ArrayList<Rule> ruleList = new ArrayList<>();
private ArrayAdapter<Rule> ruleListViewAdapter; private ArrayAdapter<Rule> ruleListViewAdapter;
@ -199,6 +200,7 @@ public class ActivityMainRules extends ActivityGeneric
AutomationService runContext = AutomationService.getInstance(); AutomationService runContext = AutomationService.getInstance();
if(runContext != null) if(runContext != null)
{ {
Miscellaneous.logEvent("i", "ActivityMainRules", "Initiating manual execution of rule " + ruleThisIsAbout.getName(), 3);
ruleThisIsAbout.activate(runContext, true); ruleThisIsAbout.activate(runContext, true);
break; break;
} }
@ -206,8 +208,8 @@ public class ActivityMainRules extends ActivityGeneric
Toast.makeText(ActivityMainRules.this, getResources().getString(R.string.serviceHasToRunForThat), Toast.LENGTH_LONG).show(); Toast.makeText(ActivityMainRules.this, getResources().getString(R.string.serviceHasToRunForThat), Toast.LENGTH_LONG).show();
break; break;
case 1: case 1:
ruleToEdit = ruleThisIsAbout;
Intent manageSpecificRuleIntent = new Intent (ActivityMainRules.this, ActivityManageRule.class); Intent manageSpecificRuleIntent = new Intent (ActivityMainRules.this, ActivityManageRule.class);
manageSpecificRuleIntent.putExtra(intentNameRuleName, ruleThisIsAbout.getName());
startActivityForResult(manageSpecificRuleIntent, requestCodeChangeRule); startActivityForResult(manageSpecificRuleIntent, requestCodeChangeRule);
break; break;
case 2: case 2:
@ -250,15 +252,5 @@ public class ActivityMainRules extends ActivityGeneric
} }
catch(NullPointerException e) catch(NullPointerException e)
{} {}
try
{
if(AutomationService.isMyServiceRunning(this))
DateTimeListener.reloadAlarms();
}
catch(NullPointerException e)
{
// AlarmManager instance not prepared, yet.
}
} }
} }

View File

@ -374,7 +374,7 @@ public class ActivityMainScreen extends ActivityGeneric
} }
catch (Exception e) catch (Exception e)
{ {
activityMainScreenInstance.tvLastRule.setText("n./a."); activityMainScreenInstance.tvLastProfile.setText("n./a.");
} }
} }
else else

View File

@ -378,7 +378,7 @@ public class ActivityManageActionStartActivity extends Activity
public void onClick(View v) public void onClick(View v)
{ {
int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion; int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && targetSdkVersion >= 30) if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && targetSdkVersion >= 30 && !ActivityPermissions.havePermission(Manifest.permission.QUERY_ALL_PACKAGES, ActivityManageActionStartActivity.this))// && shouldShowRequestPermissionRationale(Manifest.permission.QUERY_ALL_PACKAGES))
{ {
requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission); requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission);
} }

View File

@ -34,7 +34,6 @@ public class ActivityManagePoi extends Activity
public LocationManager myLocationManager; public LocationManager myLocationManager;
MyLocationListenerGps myLocationListenerGps = new MyLocationListenerGps(); MyLocationListenerGps myLocationListenerGps = new MyLocationListenerGps();
Location locationGps = null, locationNetwork = null; Location locationGps = null, locationNetwork = null;
// Location locationWifi = null;
MyLocationListenerNetwork myLocationListenerNetwork = new MyLocationListenerNetwork(); MyLocationListenerNetwork myLocationListenerNetwork = new MyLocationListenerNetwork();
Button bGetPosition, bSavePoi; Button bGetPosition, bSavePoi;
ImageButton ibShowOnMap; ImageButton ibShowOnMap;

View File

@ -70,12 +70,13 @@ public class ActivityManageRule extends Activity
static int triggerBattery; static int triggerBattery;
static double triggerSpeed; static double triggerSpeed;
static double triggerNoise; static double triggerNoise;
static Rule ruleToEdit;
static boolean newRule; static boolean newRule;
static Trigger newTrigger; static Trigger newTrigger;
static Action newAction; static Action newAction;
Rule ruleToEdit = null;
ArrayAdapter<Trigger> triggerListViewAdapter; ArrayAdapter<Trigger> triggerListViewAdapter;
ArrayAdapter<Action> actionListViewAdapter; ArrayAdapter<Action> actionListViewAdapter;
@ -130,10 +131,10 @@ public class ActivityManageRule extends Activity
@Override @Override
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
{ {
context = this;
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_specific_rule); setContentView(R.layout.activity_manage_specific_rule);
context = this;
instance = this; instance = this;
cmdTriggerAdd = (Button)findViewById(R.id.cmdTriggerAdd); cmdTriggerAdd = (Button)findViewById(R.id.cmdTriggerAdd);
@ -147,7 +148,17 @@ public class ActivityManageRule extends Activity
imageHelpButton = (ImageView)findViewById(R.id.imageHelpButton); imageHelpButton = (ImageView)findViewById(R.id.imageHelpButton);
//decide if it will be created anew or loaded to edit an existing one //decide if it will be created anew or loaded to edit an existing one
if(ActivityMainRules.ruleToEdit == null) if(getIntent().hasExtra(ActivityMainRules.intentNameRuleName))
{
// change existing rule
Miscellaneous.logEvent("i", "Rule", "Cache not empty, assuming change request.", 3);
newRule = false;
ruleToEdit = Rule.getByName(getIntent().getStringExtra(ActivityMainRules.intentNameRuleName));
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
loadVariablesIntoGui();
}
else
{ {
// new rule // new rule
Miscellaneous.logEvent("i", "Rule", "Cache empty, assuming create request.", 3); Miscellaneous.logEvent("i", "Rule", "Cache empty, assuming create request.", 3);
@ -158,16 +169,6 @@ public class ActivityManageRule extends Activity
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet()); triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet()); actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
} }
else
{
// change existing rule
Miscellaneous.logEvent("i", "Rule", "Cache not empty, assuming change request.", 3);
newRule = false;
ruleToEdit = ActivityMainRules.ruleToEdit;
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
loadVariablesIntoGui();
}
cmdTriggerAdd.setOnClickListener(new OnClickListener() cmdTriggerAdd.setOnClickListener(new OnClickListener()
{ {
@ -256,8 +257,9 @@ public class ActivityManageRule extends Activity
switch(selectedTrigger.getTriggerType()) switch(selectedTrigger.getTriggerType())
{ {
case timeFrame: case timeFrame:
ActivityManageTriggerTimeFrame.editedTimeFrameTrigger = selectedTrigger;
Intent timeFrameEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTimeFrame.class); Intent timeFrameEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTimeFrame.class);
timeFrameEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
timeFrameEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeEdit); startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeEdit);
break; break;
case bluetoothConnection: case bluetoothConnection:
@ -1232,9 +1234,15 @@ public class ActivityManageRule extends Activity
else if(requestCode == requestCodeTriggerTimeframeEdit) else if(requestCode == requestCodeTriggerTimeframeEdit)
{ {
//edit TimeFrame //edit TimeFrame
if(resultCode == RESULT_OK && ActivityManageTriggerTimeFrame.editedTimeFrameTrigger != null) if(resultCode == RESULT_OK && data.hasExtra(intentNameTriggerParameter2))
{ {
ActivityManageTriggerTimeFrame.editedTimeFrameTrigger.setParentRule(ruleToEdit); Trigger responseTimeFrame = new Trigger();
responseTimeFrame.setTriggerType(Trigger_Enum.timeFrame);
responseTimeFrame.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
responseTimeFrame.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
responseTimeFrame.setTimeFrame(new TimeFrame(data.getStringExtra(intentNameTriggerParameter2)));
responseTimeFrame.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, responseTimeFrame);
this.refreshTriggerList(); this.refreshTriggerList();
} }
else else

View File

@ -1,6 +1,7 @@
package com.jens.automation2; package com.jens.automation2;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -27,7 +28,7 @@ public class ActivityManageTriggerTimeFrame extends Activity
RadioButton radioTimeFrameEntering, radioTimeFrameLeaving; RadioButton radioTimeFrameEntering, radioTimeFrameLeaving;
EditText etRepeatEvery; EditText etRepeatEvery;
public static Trigger editedTimeFrameTrigger = null; static Trigger editedTimeFrameTrigger = null;
@Override @Override
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
@ -152,8 +153,13 @@ public class ActivityManageTriggerTimeFrame extends Activity
} }
editedTimeFrameTrigger.setTriggerParameter(radioTimeFrameEntering.isChecked()); editedTimeFrameTrigger.setTriggerParameter(radioTimeFrameEntering.isChecked());
editedTimeFrameTrigger.setTriggerParameter2(editedTimeFrameTrigger.getTimeFrame().toTriggerParameter2String());
setResult(RESULT_OK);
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, editedTimeFrameTrigger.getTriggerParameter());
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, editedTimeFrameTrigger.getTriggerParameter2());
setResult(RESULT_OK, response);
finish(); finish();
} }
}); });
@ -166,9 +172,15 @@ public class ActivityManageTriggerTimeFrame extends Activity
etRepeatEvery.setEnabled(isChecked); etRepeatEvery.setEnabled(isChecked);
} }
}); });
if(editedTimeFrameTrigger.getTimeFrame() != null) if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
editedTimeFrameTrigger = new Trigger();
editedTimeFrameTrigger.setTriggerParameter(getIntent().getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
editedTimeFrameTrigger.setTriggerParameter2(getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
editedTimeFrameTrigger.setTimeFrame(new TimeFrame(editedTimeFrameTrigger.getTriggerParameter2()));
loadVariableIntoGui(); loadVariableIntoGui();
}
} }
private void loadVariableIntoGui() private void loadVariableIntoGui()
@ -219,5 +231,4 @@ public class ActivityManageTriggerTimeFrame extends Activity
etRepeatEvery.setText(String.valueOf(editedTimeFrameTrigger.getTimeFrame().getRepetition())); etRepeatEvery.setText(String.valueOf(editedTimeFrameTrigger.getTimeFrame().getRepetition()));
} }
} }
}
}

View File

@ -904,6 +904,9 @@ public class ActivityPermissions extends Activity
case Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS: case Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS:
usingElements.add(getResources().getString(R.string.recommendedForBetterReliability)); usingElements.add(getResources().getString(R.string.recommendedForBetterReliability));
break; break;
case Manifest.permission.QUERY_ALL_PACKAGES:
usingElements.add(getResources().getString(R.string.queryAllPackages));
break;
} }
return usingElements; return usingElements;

View File

@ -28,6 +28,7 @@ import androidx.core.app.NotificationManagerCompat;
import com.jens.automation2.Trigger.Trigger_Enum; import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider; import com.jens.automation2.location.LocationProvider;
import com.jens.automation2.receivers.DateTimeListener;
import com.jens.automation2.receivers.PackageReplacedReceiver; import com.jens.automation2.receivers.PackageReplacedReceiver;
import com.jens.automation2.receivers.PhoneStatusListener; import com.jens.automation2.receivers.PhoneStatusListener;
@ -57,6 +58,8 @@ public class AutomationService extends Service implements OnInitListener
protected Calendar lockSoundChangesEnd = null; protected Calendar lockSoundChangesEnd = null;
protected boolean isRunning; protected boolean isRunning;
protected static AutomationService centralInstance = null;
public void nullLockSoundChangesEnd() public void nullLockSoundChangesEnd()
{ {
lockSoundChangesEnd = null; lockSoundChangesEnd = null;
@ -94,8 +97,6 @@ public class AutomationService extends Service implements OnInitListener
return myLocationProvider; return myLocationProvider;
} }
protected static AutomationService centralInstance = null;
public static AutomationService getInstance() public static AutomationService getInstance()
{ {
return centralInstance; return centralInstance;
@ -287,6 +288,8 @@ public class AutomationService extends Service implements OnInitListener
myLocationProvider.applySettingsAndRules(); myLocationProvider.applySettingsAndRules();
ReceiverCoordinator.applySettingsAndRules(); ReceiverCoordinator.applySettingsAndRules();
DateTimeListener.reloadAlarms();
} }
@Override @Override
@ -460,6 +463,8 @@ public class AutomationService extends Service implements OnInitListener
ttsEngine.shutdown(); ttsEngine.shutdown();
PackageReplacedReceiver.setHasServiceBeenRunning(false, this); PackageReplacedReceiver.setHasServiceBeenRunning(false, this);
centralInstance = null;
} }
protected static Builder createDefaultNotificationBuilderOld() protected static Builder createDefaultNotificationBuilderOld()

View File

@ -1840,7 +1840,8 @@ public class Miscellaneous extends Service
* @param context Context reference to get the TelephonyManager instance from * @param context Context reference to get the TelephonyManager instance from
* @return country code or null * @return country code or null
*/ */
public static String getUserCountry(Context context) { public static String getUserCountry(Context context)
{
try try
{ {
final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

View File

@ -458,29 +458,17 @@ public class Profile implements Comparable<Profile>
public boolean delete(Context context) public boolean delete(Context context)
{ {
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.profileActive)) Rule usingRule = this.isInUseByRules();
if(usingRule != null)
{ {
for (Rule rule : Rule.findRuleCandidatesByTriggerProfile(this)) Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), usingRule.getName(), this.getName()), Toast.LENGTH_LONG).show();
{ return false;
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
{
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
} }
else else
{ {
profileCollection.remove(this); profileCollection.remove(this);
return XmlFileInterface.writeFile(); return XmlFileInterface.writeFile();
} }
return false;
} }
private boolean plausibilityCheck() private boolean plausibilityCheck()

View File

@ -80,6 +80,29 @@ public class TimeFrame
this.setRepetition(Long.parseLong(dateArray[3])); this.setRepetition(Long.parseLong(dateArray[3]));
} }
public String toTriggerParameter2String()
{
StringBuilder response = new StringBuilder();
response.append(this.getTriggerTimeStart().getHours() + ":" + this.getTriggerTimeStart().getMinutes() + ":0");
response.append(separator);
response.append(this.getTriggerTimeStop().getHours() + ":" + this.getTriggerTimeStop().getMinutes() + ":0");
response.append(separator);
StringBuilder days = new StringBuilder();
for(int day : dayList)
days.append(String.valueOf(day));
response.append(days.toString());
if(this.repetition > 0)
{
response.append(separator + this.getRepetition());
}
return response.toString();
}
@Override @Override
public String toString() public String toString()
{ {

View File

@ -894,7 +894,7 @@ public class Trigger
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) < 0 Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) < 0
&& &&
(Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0 (Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
| ||
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0) Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0)
) )
@ -1548,7 +1548,6 @@ public class Trigger
} }
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.screenIs), state)); returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.screenIs), state));
break; break;
default: default:
returnString.append("error"); returnString.append("error");

View File

@ -254,8 +254,6 @@ public class XmlFileInterface
else else
serializer.text("null"); serializer.text("null");
} }
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.timeFrame)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTimeFrame().toString());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.speed) else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.speed)
serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getSpeed())); serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getSpeed()));
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.noiseLevel) else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.noiseLevel)
@ -838,7 +836,6 @@ public class XmlFileInterface
private static Trigger readTrigger(XmlPullParser parser) throws IOException, XmlPullParserException private static Trigger readTrigger(XmlPullParser parser) throws IOException, XmlPullParserException
{ {
/* FILE EXAMPE: /* FILE EXAMPE:
* ***************** * *****************
* <Automation> * <Automation>

View File

@ -189,7 +189,7 @@ public class LocationProvider
/* /*
Due to strange factors the time difference might be 0 resulting in mathematical error. Due to strange factors the time difference might be 0 resulting in mathematical error.
*/ */
if (Double.isInfinite(currentSpeed) | Double.isNaN(currentSpeed)) if (Double.isInfinite(currentSpeed) || Double.isNaN(currentSpeed))
Miscellaneous.logEvent("i", "Speed", "Error while calculating speed.", 4); Miscellaneous.logEvent("i", "Speed", "Error while calculating speed.", 4);
else else
{ {
@ -240,7 +240,7 @@ public class LocationProvider
if(Settings.positioningEngine == 0) if(Settings.positioningEngine == 0)
{ {
if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed)) if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) || Rule.isAnyRuleUsing(Trigger_Enum.speed))
{ {
// startCellLocationChangedReceiver // startCellLocationChangedReceiver
if (CellLocationChangedReceiver.isCellLocationChangedReceiverPossible()) if (CellLocationChangedReceiver.isCellLocationChangedReceiverPossible())
@ -424,7 +424,7 @@ public class LocationProvider
} }
// *********** RULE CHANGES *********** // *********** RULE CHANGES ***********
if(!CellLocationChangedReceiver.isCellLocationListenerActive() && (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed))) if(!CellLocationChangedReceiver.isCellLocationListenerActive() && (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) || Rule.isAnyRuleUsing(Trigger_Enum.speed)))
{ {
Miscellaneous.logEvent("i", "LocationProvider", "Starting NoiseListener CellLocationChangedReceiver because used in a new/changed rule.", 4); Miscellaneous.logEvent("i", "LocationProvider", "Starting NoiseListener CellLocationChangedReceiver because used in a new/changed rule.", 4);
if(CellLocationChangedReceiver.haveAllPermission()) if(CellLocationChangedReceiver.haveAllPermission())

View File

@ -40,8 +40,9 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
{ {
if(newWifiSsid.startsWith("\"") && newWifiSsid.endsWith("\"")) if(newWifiSsid.startsWith("\"") && newWifiSsid.endsWith("\""))
newWifiSsid = newWifiSsid.substring(1, newWifiSsid.length()-1); newWifiSsid = newWifiSsid.substring(1, newWifiSsid.length()-1);
WifiBroadcastReceiver.lastWifiSsid = newWifiSsid; if(newWifiSsid.length() > 0)
WifiBroadcastReceiver.lastWifiSsid = newWifiSsid;
} }
public static boolean isWifiListenerActive() public static boolean isWifiListenerActive()

View File

@ -27,12 +27,10 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
{ {
private static AutomationService automationServiceRef; private static AutomationService automationServiceRef;
private static AlarmManager centralAlarmManagerInstance; private static AlarmManager centralAlarmManagerInstance;
// private static Intent alarmIntent;
// private static PendingIntent alarmPendingIntent;
private static boolean alarmListenerActive=false; private static boolean alarmListenerActive=false;
private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>(); private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>();
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>(); private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
static PendingIntent alarmPendingIntent = null;
public static void startAlarmListener(final AutomationService automationServiceRef) public static void startAlarmListener(final AutomationService automationServiceRef)
{ {
@ -52,13 +50,9 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2); Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
Date now = new Date();
String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds());
Time passTime = Time.valueOf(timeString);
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame); ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
// ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime); for(int i=0; i < allRulesWithNowInTimeFrame.size(); i++)
for(int i=0; i<allRulesWithNowInTimeFrame.size(); i++)
{ {
if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context)) if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context))
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false); allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
@ -77,23 +71,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
clearAlarms(); clearAlarms();
int i=0; int i=0;
// // get a Calendar object with current time
// Calendar cal = Calendar.getInstance();
// // add 5 minutes to the calendar object
// cal.add(Calendar.SECOND, 10);
// String calSetWorkingCopyString2 = null;
// SimpleDateFormat sdf2 = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
// if (cal != null)
// {
// calSetWorkingCopyString2 = sdf2.format(cal.getTime());
// }
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of hardcoded test: beginning at " + calSetWorkingCopyString2);
// Intent alarmIntent2 = new Intent(automationServiceRef, AlarmListener.class);
// PendingIntent alarmPendingIntent2 = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent2, 0);
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent2);
// requestCodeList.add(0);
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>(); ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame); allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
@ -161,7 +139,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
} }
i++; i++;
i=(int)System.currentTimeMillis(); i = (int)System.currentTimeMillis();
sdf.format(calSetWorkingCopy.getTime()); sdf.format(calSetWorkingCopy.getTime());
String.valueOf(i); String.valueOf(i);
@ -264,11 +242,10 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
} }
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class); Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent); centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm"); SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm:ss");
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(scheduleCandidate.time.getTimeInMillis()); calendar.setTimeInMillis(scheduleCandidate.time.getTimeInMillis());
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4); Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
@ -280,7 +257,8 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
for(int requestCode : requestCodeList) for(int requestCode : requestCodeList)
{ {
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class); Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0); if(alarmPendingIntent == null)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
// Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode)); // Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode));
centralAlarmManagerInstance.cancel(alarmPendingIntent); centralAlarmManagerInstance.cancel(alarmPendingIntent);
} }
@ -316,7 +294,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
{ {
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4); Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
clearAlarms(); clearAlarms();
// centralAlarmManagerInstance.cancel(alarmPendingIntent); centralAlarmManagerInstance.cancel(alarmPendingIntent);
alarmListenerActive = false; alarmListenerActive = false;
} }
else else
@ -403,8 +381,6 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
calSet.set(Calendar.SECOND, 0); calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0); calSet.set(Calendar.MILLISECOND, 0);
// if(this.applies(null))
// {
// If the starting time is a day ahead remove 1 day. // If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis()) if(calSet.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1); calSet.add(Calendar.DAY_OF_MONTH, -1);
@ -419,11 +395,8 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
* Das war mal aktiviert. Allerdings: Die ganze Funktion liefert zurück, wenn die Regel NOCH nicht * Das war mal aktiviert. Allerdings: Die ganze Funktion liefert zurück, wenn die Regel NOCH nicht
* zutrifft, aber wir z.B. gleich den zeitlichen Bereich betreten. * zutrifft, aber wir z.B. gleich den zeitlichen Bereich betreten.
*/ */
// if(trigger.checkDateTime(calSchedule.getTime(), false))
// {
return calSchedule; return calSchedule;
// }
// }
} }
else else
Miscellaneous.logEvent("i", "DateTimeListener", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5); Miscellaneous.logEvent("i", "DateTimeListener", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);

View File

@ -216,23 +216,26 @@ public class NfcReceiver
} }
NdefMessage ndefMessage = ndef.getCachedNdefMessage(); NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords(); if(ndefMessage != null)
for (NdefRecord ndefRecord : records) {
{ NdefRecord[] records = ndefMessage.getRecords();
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) for (NdefRecord ndefRecord : records)
{ {
try if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT))
{ {
return readText(ndefRecord); try
} {
catch (UnsupportedEncodingException e) return readText(ndefRecord);
{ }
Miscellaneous.logEvent("w", "NFC", "Unsupported Encoding: " + Log.getStackTraceString(e), 3); catch (UnsupportedEncodingException e)
} {
} Miscellaneous.logEvent("w", "NFC", "Unsupported Encoding: " + Log.getStackTraceString(e), 3);
} }
}
}
}
return null; return null;
} }

View File

@ -57,7 +57,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:inputType="numberSigned" /> android:inputType="text" />
</TableRow> </TableRow>
@ -78,7 +78,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:inputType="numberSigned" /> android:inputType="text" />
</TableRow> </TableRow>
<TableRow <TableRow

View File

@ -11,7 +11,7 @@
<string name="pleaseSpecifiyTrigger">Bitte geben Sie mindestens einen Auslöser an.</string> <string name="pleaseSpecifiyTrigger">Bitte geben Sie mindestens einen Auslöser an.</string>
<string name="pleaseSpecifiyAction">Bitte geben Sie mindestens eine Aktion an.</string> <string name="pleaseSpecifiyAction">Bitte geben Sie mindestens eine Aktion an.</string>
<string name="serviceWontStart">Weder Orte noch Regeln sind definitiv. Dienst wird nicht starten.</string> <string name="serviceWontStart">Weder Orte noch Regeln sind definitiv. Dienst wird nicht starten.</string>
<string name="serviceStarted">Automations-Dienst gestarted.</string> <string name="serviceStarted">Automations-Dienst gestartet.</string>
<string name="version">Version %1$s.</string> <string name="version">Version %1$s.</string>
<string name="distanceBetween">Der Abstand zwischen GPS- und Mobilfunk-Position beträgt %1$d m. Dies +1 sollte der minimale Radius sein.</string> <string name="distanceBetween">Der Abstand zwischen GPS- und Mobilfunk-Position beträgt %1$d m. Dies +1 sollte der minimale Radius sein.</string>
<string name="positioningWindowNotice">Falls Sie in einem Gebäude sind, wird empfohlen das Gerät in die Nähe eines Fensters zu bringen bis eine Position ermittelt werden konnte. Andernfalls kann es sehr lange dauern oder es funktioniert gar nicht.</string> <string name="positioningWindowNotice">Falls Sie in einem Gebäude sind, wird empfohlen das Gerät in die Nähe eines Fensters zu bringen bis eine Position ermittelt werden konnte. Andernfalls kann es sehr lange dauern oder es funktioniert gar nicht.</string>
@ -700,4 +700,5 @@
<string name="locationNotWorkingOn12">Das Abrufen des Standorts scheint unter Android 12 derzeit nicht zu funktionieren. Wenn es bei Ihnen nicht klappt, tut mir das leid. Ich werde versuchen die Ursache zu beheben, sobald mir die Ursache bekannt ist. Wenn der Donut bei Ihnen also nicht aufhört sich zu drehen, wissen Sie warum.</string> <string name="locationNotWorkingOn12">Das Abrufen des Standorts scheint unter Android 12 derzeit nicht zu funktionieren. Wenn es bei Ihnen nicht klappt, tut mir das leid. Ich werde versuchen die Ursache zu beheben, sobald mir die Ursache bekannt ist. Wenn der Donut bei Ihnen also nicht aufhört sich zu drehen, wissen Sie warum.</string>
<string name="profileXrequiresThis">Profil \"%1$s\" benötigt dies.</string> <string name="profileXrequiresThis">Profil \"%1$s\" benötigt dies.</string>
<string name="lastProfile">Letztes Profil:</string> <string name="lastProfile">Letztes Profil:</string>
<string name="queryAllPackages">Liste von installierten Anwendungen auslesen</string>
</resources> </resources>

View File

@ -699,4 +699,5 @@
<string name="locationNotWorkingOn12">Obtener la locación no parece estar funcionando en dispositivos Android 12 actualmente. Si no está funcionando para ti, lo siento. Intentaré arreglar esto tan pronto como conozca la causa. Así que si la rosquilla no deja de girar, ya sabes por qué.</string> <string name="locationNotWorkingOn12">Obtener la locación no parece estar funcionando en dispositivos Android 12 actualmente. Si no está funcionando para ti, lo siento. Intentaré arreglar esto tan pronto como conozca la causa. Así que si la rosquilla no deja de girar, ya sabes por qué.</string>
<string name="profileXrequiresThis">El perfil \"%1$s\" requiere esto.</string> <string name="profileXrequiresThis">El perfil \"%1$s\" requiere esto.</string>
<string name="lastProfile">Último perfil:</string> <string name="lastProfile">Último perfil:</string>
<string name="queryAllPackages">Obtener una lista de las aplicaciones instaladas</string>
</resources> </resources>

View File

@ -697,7 +697,8 @@
<string name="musicCheckFrequencyTitle">Frequenza dei controlli [ms]</string> <string name="musicCheckFrequencyTitle">Frequenza dei controlli [ms]</string>
<string name="musicCheckFrequencySummary">Millisecondi tra i controlli</string> <string name="musicCheckFrequencySummary">Millisecondi tra i controlli</string>
<string name="musicPlayingDetection">Rilevamento della riproduzione musicale</string> <string name="musicPlayingDetection">Rilevamento della riproduzione musicale</string>
<string name="profileXrequiresThis">Il profilo \"%1$s\" lo richiede.</string> <string name="profileXrequiresThis">Questo è richiesto dal profilo \"%1$s\".</string>
<string name="locationNotWorkingOn12">Ottenere la posizione non sembra funzionare su dispositivi Android 12 al momento. Se non funziona per te, mi dispiace. Cercherò di risolvere questo problema non appena conoscerò la causa. Quindi, se la ciambella non smette di girare, sai perché.</string> <string name="locationNotWorkingOn12">Ottenere la posizione non sembra funzionare su dispositivi Android 12 al momento. Se non funziona per te, mi dispiace. Cercherò di risolvere questo problema non appena conoscerò la causa. Quindi, se cerchio rotante non smette di girare, sai perché.</string>
<string name="lastProfile">Ultimo profilo:</string> <string name="lastProfile">Ultimo profilo:</string>
<string name="queryAllPackages">Ottenere un elenco delle applicazioni installate</string>
</resources> </resources>

View File

@ -698,4 +698,5 @@
<string name="locationNotWorkingOn12">Het verkrijgen van de locatie lijkt momenteel niet te werken op Android 12-apparaten. Als het niet voor je werkt, spijt het me. Ik zal proberen dit op te lossen zodra ik de oorzaak ken. Dus als de donut niet stopt met draaien, weet je waarom.</string> <string name="locationNotWorkingOn12">Het verkrijgen van de locatie lijkt momenteel niet te werken op Android 12-apparaten. Als het niet voor je werkt, spijt het me. Ik zal proberen dit op te lossen zodra ik de oorzaak ken. Dus als de donut niet stopt met draaien, weet je waarom.</string>
<string name="profileXrequiresThis">Profiel \"%1$s\" vereist dit.</string> <string name="profileXrequiresThis">Profiel \"%1$s\" vereist dit.</string>
<string name="lastProfile">Laatste profiel:</string> <string name="lastProfile">Laatste profiel:</string>
<string name="queryAllPackages">Een lijst met geïnstalleerde toepassingen ophalen</string>
</resources> </resources>

View File

@ -796,4 +796,5 @@
<string name="musicCheckFrequencySummary">Milliseconds between checks</string> <string name="musicCheckFrequencySummary">Milliseconds between checks</string>
<string name="locationNotWorkingOn12">Getting the location does not seem to be working on Android 12 devices currently. If it isn\'t working for you, I\'m sorry. I\'ll try to fix this as soon as I know the cause. So if the donut doesn\'t stop spinning, you know why.</string> <string name="locationNotWorkingOn12">Getting the location does not seem to be working on Android 12 devices currently. If it isn\'t working for you, I\'m sorry. I\'ll try to fix this as soon as I know the cause. So if the donut doesn\'t stop spinning, you know why.</string>
<string name="lastProfile">Last profile:</string> <string name="lastProfile">Last profile:</string>
<string name="queryAllPackages">Get a list of installed applications</string>
</resources> </resources>

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.0' classpath 'com.android.tools.build:gradle:7.1.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -0,0 +1,14 @@
Neuer Auslöser:
* Bildschirmstatus (ein/aus)
Neue Aktionen:
* Benachrichtigung erstellen
* Benachrichtigung(en) schließen
* Medienwiedergabe steuern
Fehler behoben:
* Übersetzungsfehler im niederländischen Variablentext
* Variablen wurden beim Senden von Textnachrichten nicht ersetzt
* Der Dienst startete nicht immer, nachdem das Gerät eingeschaltet wurde
* Setzen von Klingeltönen auf Android 11 und höher
* Für das Ändern von Klingeltönen ist die Speicher-lesen-Berechtigung nötig
* Profil, das nicht verwendet wurde, konnte nicht gelöscht werden
* Orientierungssensor an Geräten ohne Magnet-Sensor

View File

@ -0,0 +1,5 @@
* Fehlerbehebung: Verwaltung von Zeitraum-Auslösern wurde manchmal falsch geladen, während der Dienst lief.
* Fehlerbehebung: Zeitraum-Auslöser: Wiederholte Ausführungen haben manchmal nicht funktioniert
* Fehlerbehebung: Zeitraum-Auslöser: Wiederholte Ausführungen liefen weiter, nachdem der Dienst bereits gestoppt wurde.
* Fehlerbehebung: Die Anwendung hatte sich nicht das zuletzt verbundene WLAN gemerkt.
* Fehlerbehebung: Programm starten: Liste zum Auswählen einer Anwendung konnte nicht erzeugt werden.

View File

@ -6,4 +6,6 @@
* Fixed: Variables were not replaced when sending text messages * Fixed: Variables were not replaced when sending text messages
* Fixed: Service wouldn't always start after device has been powered on * Fixed: Service wouldn't always start after device has been powered on
* Fixed: Set ringtones on Android 11 and above * Fixed: Set ringtones on Android 11 and above
* Fixed: Permission read storage required for changing ringtones * Fixed: Permission read storage required for changing ringtones
* Fixed: Profile that were not in use, could not be deleted.
* Fixed: Orientation sensor on devices that have no magnetic sensor.

View File

@ -0,0 +1,5 @@
* Fixed: Management of DateTimeTrigger was sometimes reloaded incorrectly while service was running
* Fixed: DateTimeTrigger: Repeated executions sometimes not working
* Fixed: DateTimeTrigger: Repeated executions continued to run after service was stopped
* Fixed: App did not memorize the most recent wifi name connected to
* Fixed: No app list displayed when trying to pick which app to start

View File

@ -0,0 +1,14 @@
Nuevo disparador:
* estado de la pantalla (encendido / apagado)
Nuevas acciones:
* Crear notificación
* Cerrar notificación(es)
* Controlar la reproducción de medios
Corregido:
* Error de traducción en texto de variables holandesas
* Las variables no fueron reemplazadas al enviar mensajes de texto
* El servicio no siempre se iniciaría después de que el dispositivo se haya encendido
* Establecer tonos de llamada en Android 11 y superior
* Se requiere almacenamiento de lectura de permisos para cambiar los tonos de llamada
* Perfil que no estaba en uso, no se pudo eliminar
* Sensor de orientación en dispositivos que no tienen sensor magnético

View File

@ -0,0 +1,5 @@
* Corregido: La administración de DateTimeTrigger a veces se recargaba incorrectamente mientras se ejecutaba el servicio
* Corregido: DateTimeTrigger: Ejecuciones repetidas a veces no funcionaban
* Corregido: DateTimeTrigger: Las ejecuciones repetidas continuaron ejecutándose después de que se detuvo el servicio
* Corregido: la aplicación no memorizó el nombre wifi más reciente conectado a
* Corregido: No se muestra ninguna lista de aplicaciones al intentar elegir qué aplicación iniciar

View File

@ -0,0 +1,14 @@
Nuovo trigger:
* stato dello schermo (on / off)
Nuove azioni:
* Crea notifica
* Chiudi notifica (s)
* Controlla la riproduzione multimediale
Fissato:
* Bug di traduzione nel testo delle variabili olandesi
* Le variabili non sono state sostituite durante l'invio di messaggi di testo
* Il servizio non si avvia sempre dopo l'accensione del dispositivo
* Imposta suonerie su Android 11 e versioni successive
* Autorizzazione di lettura necessaria per cambiare le suonerie
* Profilo che non era in uso, non poteva essere eliminato
* Sensore di orientamento su dispositivi che non hanno sensore mag.

View File

@ -0,0 +1,5 @@
* Risolto: la gestione di DateTimeTrigger a volte veniva ricaricata in modo errato durante l'esecuzione del servizio
* Risolto: DateTimeTrigger: esecuzioni ripetute a volte non funzionano
* Risolto: DateTimeTrigger: esecuzioni ripetute hanno continuato a funzionare dopo l'arresto del servizio
* Risolto: l'app non memorizzava il nome wifi più recente collegato a
* Risolto: nessun elenco di app visualizzato quando si tenta di scegliere quale app avviare

View File

@ -0,0 +1,11 @@
* Nieuwe trigger: schermstatus (aan / uit)
* Nieuwe actie: Melding maken
* Nieuwe actie: Sluit melding (en)
* Nieuwe actie: Bedien het afspelen van media
* Fixed: Vertaling bug in Nederlandse variabelen tekst
* Opgelost: Variabelen zijn niet vervangen bij het verzenden van sms-berichten
* Opgelost: service start niet altijd nadat het apparaat is ingeschakeld
* Opgelost: stel beltonen in op Android 11 en hoger
* Opgelost: Toestemming leesopslag vereist voor het wijzigen van beltonen
* Opgelost: Profiel dat niet in gebruik was, kon niet worden verwijderd.
* Vast: Oriëntatiesensor op apparaten die geen magnetische sensor hebben.

View File

@ -0,0 +1,5 @@
* Opgelost: beheer van DateTimeTrigger werd soms onjuist opnieuw geladen terwijl de service werd uitgevoerd
* Opgelost: DateTimeTrigger: Herhaalde uitvoeringen soms niet werken
* Opgelost: DateTimeTrigger: Herhaalde uitvoeringen bleven lopen nadat de service was gestopt
* Opgelost: app heeft de meest recente wifi-naam die is verbonden met
* Opgelost: er wordt geen app-lijst weergegeven wanneer u probeert te kiezen welke app u wilt starten