35 Commits

Author SHA1 Message Date
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
b02220609b show profile on main screen 2022-02-03 14:08:47 +01:00
da244d1bbe show profile on main screen 2022-02-03 14:05:42 +01:00
d402986dc3 ringtone 2022-02-03 13:41:05 +01:00
85eee6c4da Android 11 2022-02-02 23:35:24 +01:00
34883519e4 ringtone 2022-02-02 18:06:37 +01:00
92e405d396 Media playing trigger 2022-01-30 22:19:08 +01:00
1a8ce579a7 Media playing trigger 2022-01-30 22:08:55 +01:00
5899dd86f5 media playback listener 2022-01-30 20:13:56 +01:00
9387e8bdb2 media playback listener 2022-01-29 02:12:55 +01:00
5ed024774e Control media playback 2022-01-27 23:05:54 +01:00
e76f9f69db control media playback 2022-01-27 11:35:46 +01:00
0f1a12d28f control media playback 2022-01-27 11:34:04 +01:00
abaa961d3a Control media playback 2022-01-26 22:53:02 +01:00
5f0eab5b30 control media playback 2022-01-26 21:40:29 +01:00
92cb71ff2d Control media playback 2022-01-25 23:10:37 +01:00
71adc83b39 control media playback 2022-01-25 18:08:46 +01:00
88f4d65b19 control media playback 2022-01-24 20:13:35 +01:00
0c5b4d3874 screen state trigger 2022-01-23 18:54:17 +01:00
d64ea8454e screen state trigger 2022-01-22 02:20:34 +01:00
94f6418076 notification action 2022-01-21 21:52:27 +01:00
83ee19b4fa ScreenStateReceiver 2022-01-21 20:57:42 +01:00
5ed6097ed6 libs updated 2022-01-21 19:28:42 +01:00
7e9d03104c Merge remote-tracking branch 'origin/development-stable' into development 2022-01-21 14:31:04 +01:00
2e3e829abb Bugfix in sendTextMessage variable replacement 2022-01-21 13:56:21 +01:00
53 changed files with 2012 additions and 1531 deletions

View File

@ -8,11 +8,11 @@ android {
defaultConfig {
applicationId "com.jens.automation2"
minSdkVersion 16
compileSdkVersion 29
compileSdkVersion 31
buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy'
versionCode 118
versionName "1.7.3"
versionName "1.7.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -28,10 +28,6 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
flavorDimensions "version"
@ -57,6 +53,10 @@ android {
targetSdkVersion 28
}
}
lint {
abortOnError false
checkReleaseBuilds false
}
}
dependencies {
@ -72,9 +72,9 @@ dependencies {
//implementation "androidx.security:security-crypto:1.0.0"
//implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

View File

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

View File

@ -66,6 +66,7 @@
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-feature
android:name="android.hardware.telephony"
@ -73,6 +74,12 @@
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<queries>
<intent>
<action
android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
<application
android:allowBackup="true"
@ -157,6 +164,7 @@
<activity android:name=".ActivityManageTriggerDeviceOrientation" />
<activity android:name=".ActivityHelp" />
<activity android:name=".ActivityManageActionVibrate" />
<activity android:name=".ActivityManageActionControlMedia" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@ -21,8 +22,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@ -312,19 +312,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@ -351,7 +344,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@ -433,7 +429,7 @@ public class Rule implements Comparable<Rule>
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())
android.os.Debug.waitForDebugger();
@ -441,7 +437,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@ -476,66 +472,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @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 doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
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);
String message;
if(!doToggle)
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());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
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);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
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 = "";
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);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
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);
// }
// 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;
// }
// Keep log of last x rule activations (Settings)
try
{
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 = "";
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;
}
@ -544,7 +531,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
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)
@ -553,13 +543,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
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
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@ -608,186 +618,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -810,29 +640,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@ -931,4 +738,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}

View File

@ -64,6 +64,7 @@
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-feature
android:name="android.hardware.telephony"
@ -71,6 +72,12 @@
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<queries>
<intent>
<action
android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
<application
android:allowBackup="true"
@ -155,6 +162,7 @@
<activity android:name=".ActivityManageTriggerDeviceOrientation" />
<activity android:name=".ActivityHelp" />
<activity android:name=".ActivityManageActionVibrate" />
<activity android:name=".ActivityManageActionControlMedia" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@ -18,8 +19,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@ -45,7 +45,7 @@ public class Rule implements Comparable<Rule>
{
this.lastExecution = lastExecution;
}
public boolean isRuleToggle()
{
return ruleToggle;
@ -309,19 +309,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@ -348,7 +341,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@ -406,7 +402,7 @@ public class Rule implements Comparable<Rule>
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())
android.os.Debug.waitForDebugger();
@ -414,7 +410,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@ -449,66 +445,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @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 doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
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);
String message;
if(!doToggle)
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());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
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);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
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 = "";
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);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
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);
// }
// 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;
// }
// Keep log of last x rule activations (Settings)
try
{
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 = "";
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;
}
@ -517,7 +504,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
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)
@ -526,13 +516,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
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
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@ -581,186 +591,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -783,29 +613,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@ -904,4 +711,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}

View File

@ -65,6 +65,7 @@
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<application
android:allowBackup="true"
@ -149,6 +150,7 @@
<activity android:name=".ActivityManageTriggerDeviceOrientation" />
<activity android:name=".ActivityHelp" />
<activity android:name=".ActivityManageActionVibrate" />
<activity android:name=".ActivityManageActionControlMedia" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@ -21,8 +22,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@ -312,19 +312,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@ -351,7 +344,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@ -433,7 +429,7 @@ public class Rule implements Comparable<Rule>
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())
android.os.Debug.waitForDebugger();
@ -441,7 +437,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@ -476,66 +472,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @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 doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
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);
String message;
if(!doToggle)
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());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
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);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
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 = "";
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);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
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);
// }
// 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;
// }
// Keep log of last x rule activations (Settings)
try
{
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 = "";
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;
}
@ -544,7 +531,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
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)
@ -553,13 +543,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
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
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@ -608,186 +618,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -810,29 +640,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@ -931,4 +738,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}

View File

@ -2,6 +2,7 @@ package com.jens.automation2;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
@ -17,7 +18,7 @@ public class Action
Rule parentRule = null;
public static final String actionParameter2Split = "ap2split";
public static final String intentPairSeperator = "intPairSplit";
public static final String intentPairSeparator = "intPairSplit";
public static final String vibrateSeparator = ",";
public enum Action_Enum {
@ -41,6 +42,7 @@ public class Action
setDataConnection,
speakText,
playMusic,
controlMediaPlayback,
setScreenBrightness,
playSound,
vibrate,
@ -104,6 +106,8 @@ public class Action
return context.getResources().getString(R.string.actionSpeakText);
case playMusic:
return context.getResources().getString(R.string.actionPlayMusic);
case controlMediaPlayback:
return context.getResources().getString(R.string.actionMediaControl);
case playSound:
return context.getResources().getString(R.string.playSound);
case sendTextMessage:
@ -160,7 +164,6 @@ public class Action
{
StringBuilder returnString = new StringBuilder();
try
{
switch (getAction())
@ -225,6 +228,9 @@ public class Action
case playMusic:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionPlayMusic));
break;
case controlMediaPlayback:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionMediaControl));
break;
case sendTextMessage:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendTextMessage));
break;
@ -271,7 +277,7 @@ public class Action
}
else if (this.getAction().equals(Action_Enum.startOtherActivity))
{
returnString.append(": " + parameter2.replace(Action.intentPairSeperator, "/"));
returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/"));
}
else if (this.getAction().equals(Action_Enum.sendTextMessage))
{
@ -311,6 +317,34 @@ public class Action
returnString.append(", " + Miscellaneous.getAnyContext().getResources().getString(R.string.ifString) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.text) + " " + Trigger.getMatchString(parts[3]) + " " + parts[4]);
}
else if(this.getAction().equals(Action_Enum.controlMediaPlayback))
{
returnString.append(": ");
switch (this.getParameter2())
{
case "0":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.playPause));
break;
case "1":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.play));
break;
case "2":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.pause));
break;
case "3":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.stop));
break;
case "4":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.previous));
break;
case "5":
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.next));
break;
default:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.unknown));
}
}
else if (parameter2 != null && parameter2.length() > 0)
returnString.append(": " + parameter2.replace(Action.actionParameter2Split, "; "));
}
@ -475,6 +509,9 @@ public class Action
case playMusic:
Actions.playMusic(this.getParameter1(), toggleActionIfPossible);
break;
case controlMediaPlayback:
Actions.controlMediaPlayback(context, Integer.parseInt(getParameter2()));
break;
case sendTextMessage:
Actions.sendTextMessage(context, this.getParameter2().split(Actions.smsSeparator));
break;
@ -491,7 +528,10 @@ public class Action
Actions.createNotification(this);
break;
case closeNotification:
Actions.closeNotification(this);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
Actions.closeNotification(this);
else
Miscellaneous.logEvent("w", "Close notification", "Close notification was requested, but OS version is too low: " + String.valueOf(Build.VERSION.SDK_INT), 2);
break;
default:
Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3);

View File

@ -1,12 +1,8 @@
package com.jens.automation2;
import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT;
import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
@ -14,25 +10,29 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telephony.SmsManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
@ -71,9 +71,8 @@ import eu.chainfire.libsuperuser.Shell;
public class Actions
{
public static AutomationService autoMationServerRef;
public static AutomationService automationServerRef;
public static Context context;
public static Context rootetcontext;
private static Intent playMusicIntent;
private static boolean suAvailable = false;
private static String suVersion = null;
@ -227,7 +226,7 @@ public class Actions
Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState), 4);
if (desiredState && Settings.useWifiForPositioning)
WifiBroadcastReceiver.startWifiReceiver(autoMationServerRef.getLocationProvider());
WifiBroadcastReceiver.startWifiReceiver(automationServerRef.getLocationProvider());
WifiManager myWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@ -1037,7 +1036,7 @@ public class Actions
// Pack intents
for (int i = 3; i < params.length; i++)
{
String[] singleParam = params[i].split(Action.intentPairSeperator);
String[] singleParam = params[i].split(Action.intentPairSeparator);
/*Class c = Class.forName(singleParam[0]);
for(Method m : c.getMethods())
@ -1117,14 +1116,14 @@ public class Actions
}
if (params[2].equals(ActivityManageActionStartActivity.startByActivityString))
autoMationServerRef.startActivity(externalActivityIntent);
automationServerRef.startActivity(externalActivityIntent);
else
autoMationServerRef.sendBroadcast(externalActivityIntent);
automationServerRef.sendBroadcast(externalActivityIntent);
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "StartOtherApp", autoMationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2);
Toast.makeText(autoMationServerRef, autoMationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + e.getMessage(), Toast.LENGTH_LONG).show();
Miscellaneous.logEvent("e", "StartOtherApp", automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2);
Toast.makeText(automationServerRef, automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@ -1181,7 +1180,7 @@ public class Actions
PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, Actions.class), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, pi, null);
sms.sendTextMessage(phoneNumber, null, textToSend, pi, null);
}
catch (Exception e)
{
@ -1308,7 +1307,7 @@ public class Actions
try
{
boolean isEnabled = ConnectivityReceiver.isAirplaneMode(autoMationServerRef);
boolean isEnabled = ConnectivityReceiver.isAirplaneMode(automationServerRef);
if (isEnabled)
Miscellaneous.logEvent("i", "Airplane mode", "Current status is enabled.", 4);
@ -1422,7 +1421,7 @@ public class Actions
try
{
String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context);
autoMationServerRef.speak(textToSpeak, true);
automationServerRef.speak(textToSpeak, true);
}
catch (Exception e)
{
@ -1452,23 +1451,7 @@ public class Actions
playMusicIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(playMusicIntent);
// playMusicIntent = new Intent();
// playMusicIntent.setAction(android.content.Intent.ACTION_VIEW);
// File file = new File(YOUR_SONG_URI);
// playMusicIntent.setDataAndType(Uri.fromFile(file), "audio/*");
// context.startActivity(playMusicIntent);
return true;
// }
// else
// {
// if(playMusicIntent != null)
// {
// context.stopService(playMusicIntent);
// }
// }
// return false;
}
catch (ActivityNotFoundException e)
{
@ -1484,6 +1467,45 @@ public class Actions
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static boolean controlMediaPlayback(Context context, int command)
{
int keyCode = -1;
switch(command)
{
case 0:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
break;
case 1:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
break;
case 2:
keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE;
break;
case 3:
keyCode = KeyEvent.KEYCODE_MEDIA_STOP;
break;
case 4:
keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
break;
case 5:
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
break;
}
return controlMediaByDispatch(keyCode);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
static boolean controlMediaByDispatch(int keyCode)
{
AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
mAudioManager.dispatchMediaKeyEvent(event);
return true;
}
private String getTransactionCode()
{
try
@ -1597,7 +1619,7 @@ public class Actions
{
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1)
{
if(MobileDataStuff.setMobileNetworkFromAndroid9(desiredState, autoMationServerRef))
if(MobileDataStuff.setMobileNetworkFromAndroid9(desiredState, automationServerRef))
{
Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2);
return true;
@ -1610,7 +1632,7 @@ public class Actions
}
else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)
{
if (MobileDataStuff.setMobileNetworkTillAndroid5(desiredState, autoMationServerRef))
if (MobileDataStuff.setMobileNetworkTillAndroid5(desiredState, automationServerRef))
{
Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2);
return true;
@ -1623,7 +1645,7 @@ public class Actions
}
else
{
if (MobileDataStuff.setMobileNetworkAndroid6Till8(desiredState, autoMationServerRef))
if (MobileDataStuff.setMobileNetworkAndroid6Till8(desiredState, automationServerRef))
{
Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2);
return true;

View File

@ -21,6 +21,7 @@ import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
public class ActivityControlCenter extends Activity
{
@ -347,7 +348,24 @@ public class ActivityControlCenter extends Activity
systemInfoText.append("Device: " + android.os.Build.DEVICE + Miscellaneous.lineSeparator);
systemInfoText.append("Model: " + android.os.Build.MODEL + Miscellaneous.lineSeparator);
systemInfoText.append("Product: " + android.os.Build.PRODUCT + Miscellaneous.lineSeparator);
systemInfoText.append("Flavor: " + BuildConfig.FLAVOR);
systemInfoText.append("Flavor: " + BuildConfig.FLAVOR + Miscellaneous.lineSeparator);
systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator);
systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName());
/*
I've checked the Locale methods on my Android 4.1.2 device, and the results:
Locale.getDefault().getLanguage() ---> en
Locale.getDefault().getISO3Language() ---> eng
Locale.getDefault().getCountry() ---> US
Locale.getDefault().getISO3Country() ---> USA
Locale.getDefault().getDisplayCountry() ---> United States
Locale.getDefault().getDisplayName() ---> English (United States)
Locale.getDefault().toString() ---> en_US
Locale.getDefault().getDisplayLanguage()---> English
Locale.getDefault().toLanguageTag() ---> en-US
*/
return systemInfoText.toString();
}

View File

@ -199,6 +199,7 @@ public class ActivityMainRules extends ActivityGeneric
AutomationService runContext = AutomationService.getInstance();
if(runContext != null)
{
Miscellaneous.logEvent("i", "ActivityMainRules", "Initiating manual execution of rule " + ruleThisIsAbout.getName(), 3);
ruleThisIsAbout.activate(runContext, true);
break;
}

View File

@ -42,7 +42,7 @@ public class ActivityMainScreen extends ActivityGeneric
ToggleButton toggleService, tbLockSound;
Button bShowHelp, bPrivacy, bAddSoundLockTIme, bDonate, bControlCenter;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration;
ListView lvRuleHistory;
ArrayAdapter<Rule> ruleHistoryListViewAdapter;
@ -68,7 +68,8 @@ public class ActivityMainScreen extends ActivityGeneric
tvActivePoi = (TextView) findViewById(R.id.tvActivePoi);
tvClosestPoi = (TextView) findViewById(R.id.tvClosestPoi);
lvRuleHistory = (ListView) findViewById(R.id.lvRuleHistory);
tvLastRule = (TextView) findViewById(R.id.tvTimeFrameHelpText);
tvLastRule = (TextView) findViewById(R.id.tvLastRule);
tvLastProfile = (TextView)findViewById(R.id.tvLastProfile);
tvMainScreenNotePermissions = (TextView) findViewById(R.id.tvMainScreenNotePermissions);
tvMainScreenNoteFeaturesFromOtherFlavor = (TextView) findViewById(R.id.tvMainScreenNoteFeaturesFromOtherFlavor);
tvMainScreenNoteLocationImpossibleBlameGoogle = (TextView) findViewById(R.id.tvMainScreenNoteLocationImpossibleBlameGoogle);
@ -365,6 +366,16 @@ public class ActivityMainScreen extends ActivityGeneric
{
activityMainScreenInstance.tvLastRule.setText("n./a.");
}
try
{
activityMainScreenInstance.tvLastProfile.setText(Profile.getLastActivatedProfile().getName());
activityMainScreenInstance.updateListView();
}
catch (Exception e)
{
activityMainScreenInstance.tvLastProfile.setText("n./a.");
}
}
else
{
@ -373,6 +384,7 @@ public class ActivityMainScreen extends ActivityGeneric
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.serviceNotRunning));
activityMainScreenInstance.tvClosestPoi.setText("");
activityMainScreenInstance.tvLastRule.setText("");
activityMainScreenInstance.tvLastProfile.setText("");
}
// uiUpdateRunning = true;

View File

@ -0,0 +1,112 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.Toast;
import androidx.annotation.Nullable;
public class ActivityManageActionControlMedia extends Activity
{
RadioButton rbMediaPlayPause, rbMediaPlay, rbMediaPause, rbMediaStop, rbMediaPrevious, rbMediaNext;
Button bSaveControlMediaAction;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_control_media);
rbMediaPlayPause = (RadioButton)findViewById(R.id.rbMediaPlayPause);
rbMediaPlay = (RadioButton)findViewById(R.id.rbMediaPlay);
rbMediaPause = (RadioButton)findViewById(R.id.rbMediaPause);
rbMediaStop = (RadioButton)findViewById(R.id.rbMediaStop);
rbMediaPrevious = (RadioButton)findViewById(R.id.rbMediaPrevious);
rbMediaNext = (RadioButton)findViewById(R.id.rbMediaNext);
bSaveControlMediaAction = (Button)findViewById(R.id.bSaveControlMediaAction);
bSaveControlMediaAction.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
if(checkInput())
{
Intent answer = new Intent();
if(rbMediaPlayPause.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "0");
else if(rbMediaPlay.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "1");
else if(rbMediaPause.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "2");
else if(rbMediaStop.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "3");
else if(rbMediaPrevious.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "4");
else if(rbMediaNext.isChecked())
answer.putExtra(ActivityManageRule.intentNameActionParameter2, "5");
setResult(RESULT_OK, answer);
finish();
}
}
});
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameActionParameter2))
{
String existing = input.getStringExtra(ActivityManageRule.intentNameActionParameter2);
switch (existing)
{
case "0":
rbMediaPlayPause.setChecked(true);
break;
case "1":
rbMediaPlay.setChecked(true);
break;
case "2":
rbMediaPause.setChecked(true);
break;
case "3":
rbMediaStop.setChecked(true);
break;
case "4":
rbMediaPrevious.setChecked(true);
break;
case "5":
rbMediaNext.setChecked(true);
break;
}
}
}
boolean checkInput()
{
if(
!rbMediaPlayPause.isChecked()
&&
!rbMediaPlay.isChecked()
&&
!rbMediaPause.isChecked()
&&
!rbMediaStop.isChecked()
&&
!rbMediaPrevious.isChecked()
&&
!rbMediaNext.isChecked()
)
{
Toast.makeText(ActivityManageActionControlMedia.this, getResources().getString(R.string.pleaseSelectActionValue), Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
}

View File

@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -123,7 +124,7 @@ public class ActivityManageActionSendTextMessage extends Activity
{
for(int i=0; i<permissions.length; i++)
{
if(permissions[i].equals("android.permission.READ_CONTACTS"))
if(permissions[i].equals(Manifest.permission.READ_CONTACTS))
{
if(grantResults[i] == PackageManager.PERMISSION_GRANTED)
{

View File

@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@ -12,6 +13,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.view.MotionEvent;
@ -30,6 +32,8 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import java.util.ArrayList;
@ -54,6 +58,8 @@ public class ActivityManageActionStartActivity extends Activity
final String urlShowExamples = "https://server47.de/automation/examples_startProgram.html";
final static String startByActivityString = "0";
final static String startByBroadcastString = "1";
final static int requestCodeForRequestQueryAllPackagesPermission = 4711;
private class CustomPackageInfo extends PackageInfo implements Comparable<CustomPackageInfo>
{
@ -331,6 +337,13 @@ public class ActivityManageActionStartActivity extends Activity
return alertDialog;
}
void getAppList()
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
@ -364,9 +377,13 @@ public class ActivityManageActionStartActivity extends Activity
@Override
public void onClick(View v)
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && targetSdkVersion >= 30)
{
requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission);
}
else
getAppList();
}
});
@ -387,9 +404,9 @@ public class ActivityManageActionStartActivity extends Activity
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(Action.intentPairSeperator))
else if(etParameterName.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(";"))
@ -403,9 +420,9 @@ public class ActivityManageActionStartActivity extends Activity
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(Action.intentPairSeperator))
else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(";"))
@ -414,7 +431,7 @@ public class ActivityManageActionStartActivity extends Activity
return;
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeperator + etParameterName.getText().toString() + Action.intentPairSeperator + etParameterValue.getText().toString();
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
spinnerParameterType.setSelection(0);
@ -661,4 +678,22 @@ public class ActivityManageActionStartActivity extends Activity
getActionStartActivityDialog1Application().show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == requestCodeForRequestQueryAllPackagesPermission)
{
for(int i = 0; i < permissions.length; i++)
{
if(permissions[i].equals(Manifest.permission.QUERY_ALL_PACKAGES) && grantResults[i] == PackageManager.PERMISSION_GRANTED)
{
getAppList();
break;
}
}
}
}
}

View File

@ -12,6 +12,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
@ -83,17 +84,17 @@ public class ActivityManagePoi extends Activity
bSavePoi = (Button)findViewById(R.id.bSavePoi);
bSavePoi.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
hideKeyboard();
@Override
public void onClick(View v)
{
hideKeyboard();
if(ActivityMainPoi.poiToEdit == null)
createPoi();
else
changePoi();
}
});
if(ActivityMainPoi.poiToEdit == null)
createPoi();
else
changePoi();
}
});
ibShowOnMap.setOnClickListener(new OnClickListener()
{
@ -136,42 +137,45 @@ public class ActivityManagePoi extends Activity
private void getLocation()
{
Criteria critNetwork = new Criteria();
critNetwork.setPowerRequirement(Criteria.POWER_LOW);
critNetwork.setAltitudeRequired(false);
critNetwork.setSpeedRequired(false);
critNetwork.setBearingRequired(false);
critNetwork.setCostAllowed(false);
critNetwork.setAccuracy(Criteria.ACCURACY_COARSE);
Criteria criteriaNetwork = new Criteria();
criteriaNetwork.setPowerRequirement(Criteria.POWER_LOW);
criteriaNetwork.setAltitudeRequired(false);
criteriaNetwork.setSpeedRequired(false);
criteriaNetwork.setBearingRequired(false);
criteriaNetwork.setCostAllowed(false);
criteriaNetwork.setAccuracy(Criteria.ACCURACY_COARSE);
Criteria criteriaGps = new Criteria();
criteriaGps.setAltitudeRequired(false);
criteriaGps.setSpeedRequired(false);
criteriaGps.setBearingRequired(false);
criteriaGps.setCostAllowed(true);
criteriaGps.setAccuracy(Criteria.ACCURACY_FINE);
Criteria critGps = new Criteria();
critGps.setAltitudeRequired(false);
critGps.setSpeedRequired(false);
critGps.setBearingRequired(false);
critGps.setCostAllowed(true);
critGps.setAccuracy(Criteria.ACCURACY_FINE);
String provider1 = myLocationManager.getBestProvider(critNetwork, true);
String provider2 = myLocationManager.getBestProvider(critGps, true);
String provider1 = myLocationManager.getBestProvider(criteriaNetwork, true);
String provider2 = myLocationManager.getBestProvider(criteriaGps, true);
// String provider3 = myLocationManager.getProvider("wifi");
if(provider1 == null | provider2 == null)
if(provider1 == null || provider2 == null)
{
Toast.makeText(this, getResources().getString(R.string.logNoSuitableProvider), Toast.LENGTH_LONG).show();
return;
}
else
{
if(provider1.equals(provider2))
Miscellaneous.logEvent("i", "POI Manager", "Both location providers are equal. Only one will be used.", 4);
locationSearchStart = Calendar.getInstance();
startTimeout();
if(!Settings.privacyLocationing || !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
if(!Settings.privacyLocationing && !ConnectivityReceiver.isDataConnectionAvailable(Miscellaneous.getAnyContext()) && !provider1.equals(provider2))
{
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider1, 3);
myLocationManager.requestLocationUpdates(provider1, 500, Settings.satisfactoryAccuracyNetwork, myLocationListenerNetwork);
}
else
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location query because private locationing is active.", 4);
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location.", 4);
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider2, 3);
myLocationManager.requestLocationUpdates(provider2, 500, Settings.satisfactoryAccuracyGps, myLocationListenerGps);
@ -310,7 +314,21 @@ public class ActivityManagePoi extends Activity
public void onClick(DialogInterface dialog, int which)
{
progressDialog = ProgressDialog.show(ActivityManagePoi.this, "", getResources().getString(R.string.gettingPosition), true, true);
getLocation();
if(Build.VERSION.SDK_INT >= 31)
{
AlertDialog dia = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.locationNotWorkingOn12), ActivityManagePoi.this);
dia.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
getLocation();
}
});
dia.show();
}
else
getLocation();
}
};
alertDialogBuilder.setMessage(text).setPositiveButton("Ok", dialogClickListener);

View File

@ -44,6 +44,8 @@ public class ActivityManageProfile extends Activity
Button bChangeSoundIncomingCalls, bChangeSoundNotifications, bSaveProfile;
TextView tvIncomingCallsRingtone, tvNotificationsRingtone;
EditText etName;
boolean guiUpdate = false;
File incomingCallsRingtone = null, notificationsRingtone = null;
@ -368,6 +370,8 @@ public class ActivityManageProfile extends Activity
public void editProfile(Profile profileToEdit)
{
guiUpdate = true;
etName.setText(ActivityMainProfiles.profileToEdit.getName());
checkBoxChangeSoundMode.setChecked(ActivityMainProfiles.profileToEdit.getChangeSoundMode());
checkBoxChangeDnd.setChecked(ActivityMainProfiles.profileToEdit.getChangeDndMode());
@ -393,6 +397,8 @@ public class ActivityManageProfile extends Activity
setIncomingCallsRingtone(ActivityMainProfiles.profileToEdit.getIncomingCallsRingtone());
setNotificationsRingtone(ActivityMainProfiles.profileToEdit.getNotificationRingtone());
guiUpdate = false;
}
private boolean loadFormValuesToVariable()

View File

@ -65,14 +65,11 @@ public class ActivityManageRule extends Activity
static ProgressDialog progressDialog = null;
static Trigger_Enum triggerType;
static boolean triggerParameter;
static PointOfInterest triggerPoi;
static String triggerProcess;
static int triggerBattery;
static double triggerSpeed;
static double triggerNoise;
static TimeFrame triggerTimeFrame;
static String triggerWifiName;
static Rule ruleToEdit;
static boolean newRule;
@ -119,6 +116,8 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionCreateNotificationEdit = 804;
final static int requestCodeActionCloseNotificationAdd = 805;
final static int requestCodeActionCloseNotificationEdit = 806;
final static int requestCodeActionControlMediaAdd = 807;
final static int requestCodeActionControlMediaEdit = 808;
public static ActivityManageRule getInstance()
{
@ -366,6 +365,11 @@ public class ActivityManageRule extends Activity
activityEditVibrateIntent.putExtra("vibratePattern", a.getParameter2());
startActivityForResult(activityEditVibrateIntent, requestCodeActionVibrateEdit);
break;
case controlMediaPlayback:
Intent activityEditControlMediaIntent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class);
activityEditControlMediaIntent.putExtra(ActivityManageRule.intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditControlMediaIntent, requestCodeActionControlMediaEdit);
break;
case createNotification:
Intent activityEditCreateNotificationIntent = new Intent(ActivityManageRule.this, ActivityManageActionCreateNotification.class);
String[] elements = a.getParameter2().split(Action.actionParameter2Split);
@ -480,7 +484,6 @@ public class ActivityManageRule extends Activity
for(int i=0; i<types.length; i++)
{
//pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped;
if(types[i].toString().equals(Trigger_Enum.pointOfInterest.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.compass_small));
else if(types[i].toString().equals(Trigger_Enum.timeFrame.toString()))
@ -505,7 +508,6 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.roaming));
else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString()))
{
// if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageSpecificRule.this, "android.permission.SEND_SMS") && !Miscellaneous.isGooglePlayInstalled(ActivityManageSpecificRule.this))
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, "android.permission.SEND_SMS"))
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
}
@ -523,6 +525,10 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.smartphone));
else if(types[i].toString().equals(Trigger_Enum.profileActive.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Trigger_Enum.musicPlaying.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Trigger_Enum.screenState.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.smartphone));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@ -583,7 +589,7 @@ public class ActivityManageRule extends Activity
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeAdd);
return;
}
else if(triggerType == Trigger_Enum.charging)
else if(triggerType == Trigger_Enum.charging || triggerType == Trigger_Enum.musicPlaying)
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
else if(triggerType == Trigger_Enum.usb_host_connection)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
@ -604,7 +610,9 @@ public class ActivityManageRule extends Activity
return;
}
else if(triggerType == Trigger_Enum.process_started_stopped)
{
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
}
else if(triggerType == Trigger_Enum.notification)
{
newTrigger.setTriggerType(Trigger_Enum.notification);
@ -684,6 +692,12 @@ public class ActivityManageRule extends Activity
startActivityForResult(bluetoothEditor, requestCodeTriggerBluetoothAdd);
return;
}
else if(triggerType == Trigger_Enum.screenState)
{
newTrigger.setTriggerType(Trigger_Enum.screenState);
getTriggerScreenStateDialog().show();
return;
}
else if(triggerType == Trigger_Enum.headsetPlugged)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
@ -694,6 +708,9 @@ public class ActivityManageRule extends Activity
}
else
getTriggerParameterDialog(context, booleanChoices).show();
if(triggerType.equals(Trigger_Enum.process_started_stopped))
Miscellaneous.messageBox(getResources().getString(R.string.info), String.format(getResources().getString(R.string.featureCeasedToWorkLastWorkingAndroidVersion), "7"), ActivityManageRule.this).show();
}
});
@ -703,7 +720,7 @@ public class ActivityManageRule extends Activity
private AlertDialog getTriggerParameterDialog(final Context myContext, final String[] choices)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectTypeOfTrigger));
alertDialogBuilder.setTitle(getResources().getString(R.string.selectParameters));
alertDialogBuilder.setItems(choices, new DialogInterface.OnClickListener()
{
@Override
@ -1015,6 +1032,33 @@ public class ActivityManageRule extends Activity
return alertDialog;
}
private AlertDialog getTriggerScreenStateDialog()
{
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle(Miscellaneous.getAnyContext().getResources().getString(R.string.selectDesiredState));
String[] choices = {
Miscellaneous.getAnyContext().getResources().getString(R.string.off),
Miscellaneous.getAnyContext().getResources().getString(R.string.on),
Miscellaneous.getAnyContext().getResources().getString(R.string.unlocked)
};
alertDialog.setItems(choices, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
newTrigger.setTriggerParameter2(String.valueOf(which));
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
}
});
return alertDialog.create();
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private AlertDialog getTriggerActivityDetectionDialog()
{
@ -1104,9 +1148,6 @@ public class ActivityManageRule extends Activity
});
AlertDialog alertDialog = alertDialogBuilder.create();
// Log.i("Amount of Applications", String.valueOf(applicationArray.length));
// Log.i("Amount of Packages", String.valueOf(ActivityManageStartActivity.getPackageListString(myContext).length));
return alertDialog;
}
@ -1143,6 +1184,7 @@ public class ActivityManageRule extends Activity
triggerProcess = activityArray[which];
newTrigger.setTriggerType(Trigger_Enum.process_started_stopped);
newTrigger.setProcessName(triggerProcess);
newTrigger.setTriggerParameter2(packageName + Trigger.triggerParameter2Split + triggerProcess);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
}
@ -1383,6 +1425,16 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionControlMediaAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(data.getStringExtra(ActivityManageRule.intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCreateNotificationAdd)
{
if(resultCode == RESULT_OK)
@ -1419,6 +1471,18 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionControlMediaEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCreateNotificationEdit)
{
if(resultCode == RESULT_OK)
@ -1581,6 +1645,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.talking));
else if(types[i].toString().equals(Action_Enum.playMusic.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.tune));
else if(types[i].toString().equals(Action_Enum.controlMediaPlayback.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.tune));
else if(types[i].toString().equals(Action_Enum.setScreenBrightness.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.brightness));
else if(types[i].toString().equals(Action_Enum.playSound.toString()))
@ -1753,6 +1819,12 @@ public class ActivityManageRule extends Activity
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionVibrate.class);
startActivityForResult(intent, requestCodeActionVibrateAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString()))
{
newAction.setAction(Action_Enum.controlMediaPlayback);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class);
startActivityForResult(intent, requestCodeActionControlMediaAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.createNotification.toString()))
{
newAction.setAction(Action_Enum.createNotification);
@ -1988,8 +2060,8 @@ public class ActivityManageRule extends Activity
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
}
protected void refreshTriggerList()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update TriggerListView", 4);

View File

@ -353,14 +353,21 @@ public class ActivityPermissions extends Activity
if(!havePermission(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, workingContext))
addToArrayListUnique(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, requiredPermissions);
for(Profile p : Profile.getProfileCollection())
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
}
if (!onlyGeneral)
{
for (Rule rule : Rule.getRuleCollection())
{
for (String singlePermission : getPermissionsForRule(rule))
{
if (!havePermission(singlePermission, workingContext))
{
if(
if (
singlePermission.equalsIgnoreCase(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
||
@ -372,14 +379,15 @@ public class ActivityPermissions extends Activity
if (!Miscellaneous.googleToBlameForLocation(true))
addToArrayListUnique(singlePermission, requiredPermissions);
}
else if(singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection))
else if (singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection))
{
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
if (!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
addToArrayListUnique(singlePermission, requiredPermissions);
}
else
addToArrayListUnique(singlePermission, requiredPermissions);
}
}
}
}
@ -518,6 +526,9 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.MODIFY_AUDIO_SETTINGS, requiredPermissions);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
addToArrayListUnique(Manifest.permission.ACCESS_NOTIFICATION_POLICY, requiredPermissions);
Profile targetProfile = Profile.getByName(action.getParameter2());
if(targetProfile.changeIncomingCallsRingtone || targetProfile.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case disableScreenRotation:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@ -527,6 +538,10 @@ public class ActivityPermissions extends Activity
break;
case playMusic:
break;
case controlMediaPlayback:
// addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions);
// addToArrayListUnique(Manifest.permission.MEDIA_CONTENT_CONTROL, requiredPermissions);
break;
case sendTextMessage:
addToArrayListUnique(Manifest.permission.SEND_SMS, requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
@ -855,6 +870,32 @@ public class ActivityPermissions extends Activity
case Manifest.permission.READ_EXTERNAL_STORAGE:
for(String ruleName : getRulesUsing(Action.Action_Enum.playSound))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.changeSoundProfile))
{
Rule tempRule = Rule.getByName(ruleName);
if(tempRule != null)
{
for (Action a : tempRule.getActionSet())
{
if (a.getAction().equals(Action.Action_Enum.changeSoundProfile))
{
Profile p = Profile.getByName(a.getParameter2());
if (p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
}
}
}
}
for(Profile p : Profile.getProfileCollection())
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
{
usingElements.add(String.format(getResources().getString(R.string.profileXrequiresThis), p.getName()));
}
}
break;
case Manifest.permission.BIND_DEVICE_ADMIN:
for(String ruleName : getRulesUsing(Action.Action_Enum.turnScreenOnOrOff))

View File

@ -218,7 +218,14 @@ public class AutomationService extends Service implements OnInitListener
// Actions.setData(true);
// ********** Test area **********
return START_STICKY;
/*
On normal phones the app is supposed to automatically restart in case of any problems.
In the emulator we want it to stop to be able to better pinpoint the root cause.
*/
if(Miscellaneous.isAndroidEmulator())
return START_NOT_STICKY;
else
return START_STICKY;
}
else
{
@ -314,12 +321,18 @@ public class AutomationService extends Service implements OnInitListener
checkForMissingBackgroundLocationPermission();
Actions.context = this;
Actions.autoMationServerRef = this;
Actions.automationServerRef = this;
startLocationProvider();
ReceiverCoordinator.startAllReceivers();
PackageReplacedReceiver.setHasServiceBeenRunning(true, this);
for(Rule r : Rule.getRuleCollection())
{
if(r.getsGreenLight(AutomationService.this))
r.activate(AutomationService.this, false);
}
}
protected void startLocationProvider()

View File

@ -8,6 +8,7 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -24,9 +25,11 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.Settings.Secure;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
@ -72,8 +75,10 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@ -84,6 +89,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import java.util.Set;
import java.util.zip.ZipEntry;
@ -1187,7 +1193,8 @@ public class Miscellaneous extends Service
public static double round(double value, int places)
{
if (places < 0) throw new IllegalArgumentException();
if (places < 0)
throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(Double.toString(value));
bd = bd.setScale(places, RoundingMode.HALF_UP);
@ -1199,7 +1206,7 @@ public class Miscellaneous extends Service
Cursor cursor = null;
try
{
String[] proj = { MediaStore.Images.Media.DATA };
String[] proj = { MediaStore.Images.Media.DATA, MediaStore.Audio.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
@ -1219,6 +1226,114 @@ public class Miscellaneous extends Service
}
}
public static String getRealPathFromURI2(final Context context, final Uri uri)
{
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
{
// ExternalStorageProvider
if (isExternalStorageDocument(uri))
{
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type))
{
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri))
{
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri))
{
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type))
{
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
else if ("video".equals(type))
{
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
else if ("audio".equals(type))
{
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme()))
{
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme()))
{
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs)
{
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try
{
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst())
{
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
}
finally
{
if (cursor != null)
cursor.close();
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri)
{
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri)
{
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri)
{
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static Method getClassMethodReflective(String className, String methodName)
{
Class foundClass = null;
@ -1719,4 +1834,68 @@ public class Miscellaneous extends Service
{
return arraySearch(requestList.toArray(new String[requestList.size()]), needle, caseSensitive, matchFullLine);
}
/**
* Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
* @param context Context reference to get the TelephonyManager instance from
* @return country code or null
*/
public static String getUserCountry(Context context) {
try
{
final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final String simCountry = tm.getSimCountryIso();
if (simCountry != null && simCountry.length() == 2)
{ // SIM country code is available
return simCountry.toLowerCase(Locale.US);
}
else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA)
{ // device is not 3G (would be unreliable)
String networkCountry = tm.getNetworkCountryIso();
if (networkCountry != null && networkCountry.length() == 2)
{ // network country code is available
return networkCountry.toLowerCase(Locale.US);
}
}
}
catch (SecurityException se)
{
return "unknown";
}
catch (Exception e)
{ }
return null;
}
public static String checksumSha(String filepath) throws IOException
{
try
{
MessageDigest md = null;
md = MessageDigest.getInstance("SHA-256");
// file hashing with DigestInputStream
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md))
{
while (dis.read() != -1)
; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
StringBuilder result = new StringBuilder();
for (byte b : md.digest())
{
result.append(String.format("%02x", b));
}
return result.toString();
}
catch (NoSuchAlgorithmException e)
{
Miscellaneous.logEvent("e", "shaChecksum", Log.getStackTraceString(e), 2);
}
return null;
}
}

View File

@ -4,10 +4,12 @@ import android.app.NotificationManager;
import android.content.ContentValues;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
@ -306,29 +308,31 @@ public class Profile implements Comparable<Profile>
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, ringtoneFile.getAbsolutePath());
// values.put(MediaStore.MediaColumns.TITLE, context.getResources().getString(R.string.app_name) + " ringtone");
// values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName().replace(".mp3", "").replace(".", ""));
values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName());
// values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, ringtoneFile.length());
// values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, ringtoneType == RingtoneManager.TYPE_RINGTONE);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, ringtoneType == RingtoneManager.TYPE_NOTIFICATION);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if(existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
Uri newRingTone = context.getContentResolver().insert(existingRingTone, values);
try
{
Uri newRingTone = null;
//TODO: This part needs to be made compatible with Android 11 and above.
if(Build.VERSION.SDK_INT > 30)
{
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if (existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
newRingTone = context.getContentResolver().insert(existingRingTone, values);
}
RingtoneManager.setActualDefaultRingtoneUri(context, ringtoneType, newRingTone);
Miscellaneous.logEvent("i", "Profile", "Ringtone set to: " + newRingTone.toString(), 1);
// Ringtone tone = RingtoneManager.getRingtone(context, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
// tone.play();
return true;
}
catch (Throwable t)
@ -454,29 +458,17 @@ public class Profile implements Comparable<Profile>
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), 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;
}
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), usingRule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
else
{
profileCollection.remove(this);
return XmlFileInterface.writeFile();
}
return false;
}
private boolean plausibilityCheck()
@ -604,65 +596,107 @@ public class Profile implements Comparable<Profile>
try
{
AudioManager am = (AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE);
NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(changeSoundMode)
if (changeSoundMode)
{
if(am.getRingerMode() != soundMode)
if (am.getRingerMode() != soundMode)
return false;
}
if(changeDndMode && Build.VERSION.SDK_INT >= 23)
if (changeDndMode && Build.VERSION.SDK_INT >= 23)
{
if(mNotificationManager.getCurrentInterruptionFilter() != dndMode)
if (mNotificationManager.getCurrentInterruptionFilter() != dndMode)
return false;
}
if(changeVolumeMusicVideoGameMedia)
if (changeVolumeMusicVideoGameMedia)
{
if(am.getStreamVolume(AudioManager.STREAM_MUSIC) != volumeMusic)
if (am.getStreamVolume(AudioManager.STREAM_MUSIC) != volumeMusic)
return false;
}
if(changeVolumeNotifications)
if (changeVolumeNotifications)
{
if(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != volumeNotifications)
if (am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != volumeNotifications)
return false;
}
if(changeVolumeAlarms)
if (changeVolumeAlarms)
{
if(am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
if (am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
return false;
}
// if(changeIncomingCallsRingtone)
// {
// if (incomingCallsRingtone != null)
// {
// applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
// }
// }
if(changeVibrateWhenRinging)
/*if (changeIncomingCallsRingtone)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if (incomingCallsRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE);
if (ringtone_uri != null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
Ringtone currentRingtone = RingtoneManager.getRingtone(context, ringtone_uri);
String title = currentRingtone.getTitle(context);
*//* Ringtone desiredRingtone = RingtoneManager.getRingtone(context, Uri.fromFile(notificationRingtone));
boolean result = currentRingtone.equals(desiredRingtone);*//*
Uri desired_ringtone = MediaStore.Audio.Media.getContentUriForPath(incomingCallsRingtone.getAbsolutePath());
// File currentRingtoneFile = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(ringtone_uri.getPath());
String desiredChecksum = Miscellaneous.checksumSha(incomingCallsRingtone.getAbsolutePath());
if (!currentChecksum.equals(desiredChecksum))
return false;
}
}
}*/
if (changeVibrateWhenRinging)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), "vibrate_when_ringing");
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
if (currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
return false;
}
else
{
int currentSetting = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
if (currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
return false;
}
}
// if(changeNotificationRingtone)
// if(notificationRingtone != null)
// applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
/*if (changeNotificationRingtone)
{
if (notificationRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION);
if (ringtone_uri == null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
File currentRingtone = new File(Settings.System.DEFAULT_NOTIFICATION_URI.getPath());
// File currentRingtone = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(currentRingtone.getAbsolutePath());
String desiredChecksum = Miscellaneous.checksumSha(notificationRingtone.getAbsolutePath());
if(!currentChecksum.equals(desiredChecksum))
return false;
}
else
return false;
}
}*/
if(changeScreenLockUnlockSound)
{
@ -730,4 +764,11 @@ public class Profile implements Comparable<Profile>
return this.oldName;
}
public static Profile getLastActivatedProfile()
{
if(Profile.profileActivationHistory != null && Profile.profileActivationHistory.size() > 0)
return Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
else
return null;
}
}

View File

@ -12,9 +12,11 @@ import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener;
import com.jens.automation2.receivers.MediaPlayerListener;
import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TimeZoneListener;
import androidx.annotation.RequiresApi;
@ -54,6 +56,8 @@ public class ReceiverCoordinator
//NotificationListener.class,
PhoneStatusListener.class,
ProcessListener.class,
MediaPlayerListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
};
}
@ -70,6 +74,7 @@ public class ReceiverCoordinator
NoiseListener.class,
PhoneStatusListener.class,
ProcessListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
};
}
@ -177,13 +182,17 @@ public class ReceiverCoordinator
// Nothing to do, just not starting this one.
}
//startBluetoothReceiver
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.bluetoothConnection))
BluetoothReceiver.startBluetoothReceiver();
//startHeadsetJackListener
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.headsetPlugged))
HeadphoneJackListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.musicPlaying))
MediaPlayerListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
}
public static void stopAllReceivers()
@ -198,6 +207,7 @@ public class ReceiverCoordinator
DateTimeListener.stopAlarmListener(AutomationService.getInstance());
NoiseListener.stopNoiseListener();
ProcessListener.stopProcessListener(AutomationService.getInstance());
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance());
try
@ -268,6 +278,28 @@ public class ReceiverCoordinator
ProcessListener.stopProcessListener(AutomationService.getInstance());
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting ScreenStateListener because used in a new/changed rule.", 4);
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
}
else
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down ScreenStateListener because not used in any rule.", 4);
ScreenStateReceiver.stopScreenStateReceiver();
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.musicPlaying))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting MediaPlayerListener because used in a new/changed rule.", 4);
MediaPlayerListener.getInstance().startListener(AutomationService.getInstance());
}
else
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down MediaPlayerListener because not used in any rule.", 4);
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
}
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
{
if (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.activityDetection))

View File

@ -66,6 +66,7 @@ public class Settings implements SharedPreferences
public static boolean executeRulesAndProfilesWithSingleClick;
public static boolean displayNewsOnMainScreen;
public static boolean automaticUpdateCheck;
public static long musicCheckFrequency;
public static boolean lockSoundChanges;
public static boolean noticeAndroid9MicrophoneShown;
@ -80,53 +81,54 @@ public class Settings implements SharedPreferences
*/
public static final String dateFormat = "E dd.MM.yyyy HH:mm:ss:ssss";
protected static final int default_positioningEngine = 0;
protected static final long default_minimumDistanceChangeForGpsUpdate = 100;
protected static final long default_minimumDistanceChangeForNetworkUpdate = 500; // in Meters
protected static final long default_satisfactoryAccuracyGps = 50;
protected static final long default_satisfactoryAccuracyNetwork = 1000;
protected static final int default_gpsTimeout = 300; // seconds
protected static final long default_minimumTimeBetweenUpdate = 30000; // in Milliseconds
protected static final boolean default_startServiceAtSystemBoot = false;
protected static final boolean default_writeLogFile = false;
protected static final long default_logLevel = 2;
protected static final int default_logFileMaxSize = 10;
protected static final boolean default_useTextToSpeechOnNormal = false;
protected static final boolean default_useTextToSpeechOnVibrate = false;
protected static final boolean default_useTextToSpeechOnSilent = false;
protected static final boolean default_muteTextToSpeechDuringCalls = true;
protected static final boolean default_useWifiForPositioning = true;
protected static final boolean default_useAccelerometerForPositioning = true;
protected static final long default_useAccelerometerAfterIdleTime = 5;
protected static final long default_accelerometerMovementThreshold = 2;
protected static final long default_speedMaximumTimeBetweenLocations = 4;
protected static final long default_timeBetweenNoiseLevelMeasurements = 60;
protected static final long default_lengthOfNoiseLevelMeasurements = 5;
protected static final long default_referenceValueForNoiseLevelMeasurements = 20;
protected static final boolean default_hasServiceBeenRunning = false;
protected static final boolean default_startServiceAfterAppUpdate = true;
protected static final boolean default_startNewThreadForRuleActivation = true;
protected static final boolean default_showIconWhenServiceIsRunning = true;
protected static final boolean default_httpAcceptAllCertificates = false;
protected static final int default_httpAttempts = 3;
protected static final int default_httpAttemptsTimeout = 60;
protected static final int default_httpAttemptGap = 2;
protected static final PointOfInterest default_lastActivePoi = null;
protected static final boolean default_rememberLastActivePoi = true;
protected static final int default_locationRingBufferSize=3;
protected static final long default_timeBetweenProcessMonitorings = 60;
protected static final long default_acceptDevicePositionSignalEveryX_MilliSeconds = 1000;
protected static final int default_activityDetectionFrequency = 60;
protected static final int default_activityDetectionRequiredProbability = 75;
protected static final boolean default_privacyLocationing = false;
protected static final int default_startScreen = 0;
protected static final int default_tabsPlacement = 0;
protected static final boolean default_executeRulesAndProfilesWithSingleClick = false;
protected static final boolean default_displayNewsOnMainScreen = false;
protected static final boolean default_automaticUpdateCheck = false;
protected static final boolean default_lockSoundChanges = false;
protected static final long default_lastNewsPolltime = -1;
protected static final long default_lastUpdateCheck = -1;
public static final int default_positioningEngine = 0;
public static final long default_minimumDistanceChangeForGpsUpdate = 100;
public static final long default_minimumDistanceChangeForNetworkUpdate = 500; // in Meters
public static final long default_satisfactoryAccuracyGps = 50;
public static final long default_satisfactoryAccuracyNetwork = 1000;
public static final int default_gpsTimeout = 300; // seconds
public static final long default_minimumTimeBetweenUpdate = 30000; // in Milliseconds
public static final boolean default_startServiceAtSystemBoot = false;
public static final boolean default_writeLogFile = false;
public static final long default_logLevel = 2;
public static final int default_logFileMaxSize = 10;
public static final boolean default_useTextToSpeechOnNormal = false;
public static final boolean default_useTextToSpeechOnVibrate = false;
public static final boolean default_useTextToSpeechOnSilent = false;
public static final boolean default_muteTextToSpeechDuringCalls = true;
public static final boolean default_useWifiForPositioning = true;
public static final boolean default_useAccelerometerForPositioning = true;
public static final long default_useAccelerometerAfterIdleTime = 5;
public static final long default_accelerometerMovementThreshold = 2;
public static final long default_speedMaximumTimeBetweenLocations = 4;
public static final long default_timeBetweenNoiseLevelMeasurements = 60;
public static final long default_lengthOfNoiseLevelMeasurements = 5;
public static final long default_referenceValueForNoiseLevelMeasurements = 20;
public static final boolean default_hasServiceBeenRunning = false;
public static final boolean default_startServiceAfterAppUpdate = true;
public static final boolean default_startNewThreadForRuleActivation = true;
public static final boolean default_showIconWhenServiceIsRunning = true;
public static final boolean default_httpAcceptAllCertificates = false;
public static final int default_httpAttempts = 3;
public static final int default_httpAttemptsTimeout = 60;
public static final int default_httpAttemptGap = 2;
public static final PointOfInterest default_lastActivePoi = null;
public static final boolean default_rememberLastActivePoi = true;
public static final int default_locationRingBufferSize=3;
public static final long default_timeBetweenProcessMonitorings = 60;
public static final long default_acceptDevicePositionSignalEveryX_MilliSeconds = 1000;
public static final int default_activityDetectionFrequency = 60;
public static final int default_activityDetectionRequiredProbability = 75;
public static final boolean default_privacyLocationing = false;
public static final int default_startScreen = 0;
public static final int default_tabsPlacement = 0;
public static final boolean default_executeRulesAndProfilesWithSingleClick = false;
public static final boolean default_displayNewsOnMainScreen = false;
public static final boolean default_automaticUpdateCheck = false;
public static final boolean default_lockSoundChanges = false;
public static final long default_lastNewsPolltime = -1;
public static final long default_lastUpdateCheck = -1;
public static final long default_musicCheckFrequency = 2500;
@Override
public boolean contains(String arg0)
@ -261,6 +263,11 @@ public class Settings implements SharedPreferences
startScreen = Integer.parseInt(prefs.getString("startScreen", String.valueOf(default_startScreen)));
tabsPlacement = Integer.parseInt(prefs.getString("tabsPlacement", String.valueOf(default_tabsPlacement)));
musicCheckFrequency = Long.parseLong(prefs.getString("musicCheckFrequency", String.valueOf(default_musicCheckFrequency)));
if(Settings.musicCheckFrequency == 0)
Settings.musicCheckFrequency = Settings.default_musicCheckFrequency;
executeRulesAndProfilesWithSingleClick = prefs.getBoolean("executeRulesAndProfilesWithSingleClick", default_executeRulesAndProfilesWithSingleClick);
automaticUpdateCheck = prefs.getBoolean("automaticUpdateCheck", default_automaticUpdateCheck);
displayNewsOnMainScreen = prefs.getBoolean("displayNewsOnMainScreen", default_displayNewsOnMainScreen);
@ -327,154 +334,154 @@ public class Settings implements SharedPreferences
Editor editor = prefs.edit();
if(!prefs.contains("startServiceAtSystemBoot") | force)
if(!prefs.contains("startServiceAtSystemBoot") || force)
editor.putBoolean("startServiceAtSystemBoot", default_startServiceAtSystemBoot);
if(!prefs.contains("writeLogFile") | force)
if(!prefs.contains("writeLogFile") || force)
editor.putBoolean("writeLogFile", default_writeLogFile);
// if(!prefs.contains("useTextToSpeech") | force)
// editor.putBoolean("useTextToSpeech", default_useTextToSpeech);
if(!prefs.contains("useTextToSpeechOnNormal") | force)
if(!prefs.contains("useTextToSpeechOnNormal") || force)
editor.putBoolean("useTextToSpeechOnNormal", default_useTextToSpeechOnNormal);
if(!prefs.contains("useTextToSpeechOnVibrate") | force)
if(!prefs.contains("useTextToSpeechOnVibrate") || force)
editor.putBoolean("useTextToSpeechOnVibrate", default_useTextToSpeechOnVibrate);
if(!prefs.contains("useTextToSpeechOnSilent") | force)
if(!prefs.contains("useTextToSpeechOnSilent") || force)
editor.putBoolean("useTextToSpeechOnSilent", default_useTextToSpeechOnSilent);
if(!prefs.contains("muteTextToSpeechDuringCalls") | force)
if(!prefs.contains("muteTextToSpeechDuringCalls") || force)
editor.putBoolean("muteTextToSpeechDuringCalls", default_muteTextToSpeechDuringCalls);
if(!prefs.contains("positioningEngine") | force)
if(!prefs.contains("positioningEngine") || force)
editor.putString("positioningEngine", String.valueOf(default_positioningEngine));
if(!prefs.contains("useWifiForPositioning") | force)
if(!prefs.contains("useWifiForPositioning") || force)
editor.putBoolean("useWifiForPositioning", default_useWifiForPositioning);
if(!prefs.contains("hasServiceBeenRunning") | force)
if(!prefs.contains("hasServiceBeenRunning") || force)
editor.putBoolean("hasServiceBeenRunning", default_hasServiceBeenRunning);
if(!prefs.contains("startServiceAfterAppUpdate") | force)
if(!prefs.contains("startServiceAfterAppUpdate") || force)
editor.putBoolean("startServiceAfterAppUpdate", default_startServiceAfterAppUpdate);
if(!prefs.contains("startNewThreadForRuleActivation") | force)
if(!prefs.contains("startNewThreadForRuleActivation") || force)
editor.putBoolean("startNewThreadForRuleActivation", default_startNewThreadForRuleActivation);
if(!prefs.contains("showIconWhenServiceIsRunning") | force)
if(!prefs.contains("showIconWhenServiceIsRunning") || force)
editor.putBoolean("showIconWhenServiceIsRunning", default_showIconWhenServiceIsRunning);
if(!prefs.contains("useAccelerometerForPositioning") | force)
if(!prefs.contains("useAccelerometerForPositioning") || force)
editor.putBoolean("useAccelerometerForPositioning", default_useAccelerometerForPositioning);
if(!prefs.contains("useAccelerometerAfterIdleTime") | force)
if(!prefs.contains("useAccelerometerAfterIdleTime") || force)
editor.putString("useAccelerometerAfterIdleTime", String.valueOf(default_useAccelerometerAfterIdleTime));
if(!prefs.contains("accelerometerMovementThreshold") | force)
if(!prefs.contains("accelerometerMovementThreshold") || force)
editor.putString("accelerometerMovementThreshold", String.valueOf(default_accelerometerMovementThreshold));
if(!prefs.contains("speedMaximumTimeBetweenLocations") | force)
if(!prefs.contains("speedMaximumTimeBetweenLocations") || force)
editor.putString("speedMaximumTimeBetweenLocations", String.valueOf(default_speedMaximumTimeBetweenLocations));
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE") | force)
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE") || force)
editor.putString("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE", String.valueOf(default_minimumDistanceChangeForGpsUpdate));
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE") | force)
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE") || force)
editor.putString("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE", String.valueOf(default_minimumDistanceChangeForNetworkUpdate));
if(!prefs.contains("SATISFACTORY_ACCURACY_GPS") | force)
if(!prefs.contains("SATISFACTORY_ACCURACY_GPS") || force)
editor.putString("SATISFACTORY_ACCURACY_GPS", String.valueOf(default_satisfactoryAccuracyGps));
if(!prefs.contains("SATISFACTORY_ACCURACY_NETWORK") | force)
if(!prefs.contains("SATISFACTORY_ACCURACY_NETWORK") || force)
editor.putString("SATISFACTORY_ACCURACY_NETWORK", String.valueOf(default_satisfactoryAccuracyNetwork));
if(!prefs.contains("gpsTimeout") | force)
if(!prefs.contains("gpsTimeout") || force)
editor.putString("gpsTimeout", String.valueOf(default_gpsTimeout));
if(!prefs.contains("MINIMUM_TIME_BETWEEN_UPDATE") | force)
if(!prefs.contains("MINIMUM_TIME_BETWEEN_UPDATE") || force)
editor.putString("MINIMUM_TIME_BETWEEN_UPDATE", String.valueOf(default_minimumTimeBetweenUpdate));
if(!prefs.contains("timeBetweenNoiseLevelMeasurements") | force)
if(!prefs.contains("timeBetweenNoiseLevelMeasurements") || force)
editor.putString("timeBetweenNoiseLevelMeasurements", String.valueOf(default_timeBetweenNoiseLevelMeasurements));
if(!prefs.contains("lengthOfNoiseLevelMeasurements") | force)
if(!prefs.contains("lengthOfNoiseLevelMeasurements") || force)
editor.putString("lengthOfNoiseLevelMeasurements", String.valueOf(default_lengthOfNoiseLevelMeasurements));
if(!prefs.contains("referenceValueForNoiseLevelMeasurements") | force)
if(!prefs.contains("referenceValueForNoiseLevelMeasurements") || force)
editor.putString("referenceValueForNoiseLevelMeasurements", String.valueOf(default_referenceValueForNoiseLevelMeasurements));
if(!prefs.contains("logLevel") | force)
if(!prefs.contains("logLevel") || force)
editor.putString("logLevel", String.valueOf(default_logLevel));
if(!prefs.contains("logFileMaxSize") | force)
if(!prefs.contains("logFileMaxSize") || force)
editor.putString("logFileMaxSize", String.valueOf(default_logFileMaxSize));
if(!prefs.contains("httpAcceptAllCertificates") | force)
if(!prefs.contains("httpAcceptAllCertificates") || force)
editor.putBoolean("httpAcceptAllCertificates", default_httpAcceptAllCertificates);
if(!prefs.contains("httpAttempts") | force)
if(!prefs.contains("httpAttempts") || force)
editor.putString("httpAttempts", String.valueOf(default_httpAttempts));
if(!prefs.contains("httpAttemptsTimeout") | force)
if(!prefs.contains("httpAttemptsTimeout") || force)
editor.putString("httpAttemptsTimeout", String.valueOf(default_httpAttemptsTimeout));
if(!prefs.contains("httpAttemptGap") | force)
if(!prefs.contains("httpAttemptGap") || force)
editor.putString("httpAttemptGap", String.valueOf(default_httpAttemptGap));
if(!prefs.contains("lastActivePoi") | force)
if(!prefs.contains("lastActivePoi") || force)
editor.putString("lastActivePoi", "null");
if(!prefs.contains("rememberLastActivePoi") | force)
if(!prefs.contains("rememberLastActivePoi") || force)
editor.putBoolean("rememberLastActivePoi", default_rememberLastActivePoi);
if(!prefs.contains("locationRingBufferSize") | force)
if(!prefs.contains("locationRingBufferSize") || force)
editor.putString("locationRingBufferSize", String.valueOf(default_locationRingBufferSize));
if(!prefs.contains("timeBetweenProcessMonitorings") | force)
if(!prefs.contains("timeBetweenProcessMonitorings") || force)
editor.putString("timeBetweenProcessMonitorings", String.valueOf(default_timeBetweenProcessMonitorings));
if(!prefs.contains("acceptDevicePositionSignalEveryX_MilliSeconds") | force)
if(!prefs.contains("acceptDevicePositionSignalEveryX_MilliSeconds") || force)
editor.putString("acceptDevicePositionSignalEveryX_MilliSeconds", String.valueOf(default_acceptDevicePositionSignalEveryX_MilliSeconds));
if(!prefs.contains("activityDetectionFrequency") | force)
if(!prefs.contains("activityDetectionFrequency") || force)
editor.putString("activityDetectionFrequency", String.valueOf(default_activityDetectionFrequency));
if(!prefs.contains("activityDetectionRequiredProbability") | force)
if(!prefs.contains("activityDetectionRequiredProbability") || force)
editor.putString("activityDetectionRequiredProbability", String.valueOf(default_activityDetectionRequiredProbability));
if(!prefs.contains("privacyLocationing") | force)
if(!prefs.contains("privacyLocationing") || force)
editor.putBoolean("privacyLocationing", default_privacyLocationing);
if(!prefs.contains("startScreen") | force)
if(!prefs.contains("startScreen") || force)
editor.putString("startScreen", String.valueOf(default_startScreen));
if(!prefs.contains("tabsPlacement") | force)
if(!prefs.contains("tabsPlacement") || force)
editor.putString("tabsPlacement", String.valueOf(default_tabsPlacement));
if(!prefs.contains("executeRulesAndProfilesWithSingleClick") | force)
if(!prefs.contains("executeRulesAndProfilesWithSingleClick") || force)
editor.putBoolean("executeRulesAndProfilesWithSingleClick", default_executeRulesAndProfilesWithSingleClick);
if(!prefs.contains("automaticUpdateCheck") | force)
if(!prefs.contains("automaticUpdateCheck") || force)
editor.putBoolean("automaticUpdateCheck", default_automaticUpdateCheck);
if(!prefs.contains("displayNewsOnMainScreen") | force)
if(!prefs.contains("displayNewsOnMainScreen") || force)
editor.putBoolean("displayNewsOnMainScreen", default_displayNewsOnMainScreen);
if(!prefs.contains("lockSoundChanges") | force)
if(!prefs.contains("musicCheckFrequency") || force)
editor.putLong("musicCheckFrequency", default_musicCheckFrequency);
if(!prefs.contains("lockSoundChanges") || force)
editor.putBoolean("lockSoundChanges", default_lockSoundChanges);
if(!prefs.contains("noticeAndroid9MicrophoneShown") | force)
if(!prefs.contains("noticeAndroid9MicrophoneShown") || force)
editor.putBoolean("noticeAndroid9MicrophoneShown", false);
if(!prefs.contains("lastNewsPolltime") | force)
if(!prefs.contains("lastNewsPolltime") || force)
editor.putLong("lastNewsPolltime", default_lastNewsPolltime);
if(!prefs.contains("lastUpdateCheck") | force)
if(!prefs.contains("lastUpdateCheck") || force)
editor.putLong("lastUpdateCheck", default_lastUpdateCheck);
if(!prefs.contains("whatHasBeenDone") | force)
if(!prefs.contains("whatHasBeenDone") || force)
editor.putString("whatHasBeenDone", "");
editor.commit();
@ -543,6 +550,10 @@ public class Settings implements SharedPreferences
editor.putBoolean("automaticUpdateCheck", automaticUpdateCheck);
editor.putBoolean("displayNewsOnMainScreen", displayNewsOnMainScreen);
if(Settings.musicCheckFrequency == 0)
Settings.musicCheckFrequency = Settings.default_musicCheckFrequency;
editor.putString("musicCheckFrequency", String.valueOf(musicCheckFrequency));
editor.putBoolean("lockSoundChanges", lockSoundChanges);
editor.putBoolean("noticeAndroid9MicrophoneShown", noticeAndroid9MicrophoneShown);
editor.putBoolean("noticeAndroid10WifiShown", noticeAndroid10WifiShown);

View File

@ -17,11 +17,15 @@ import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener;
import com.jens.automation2.receivers.MediaPlayerListener;
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 com.jens.automation2.receivers.ScreenStateReceiver;
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;
@ -34,6 +38,61 @@ import java.util.Date;
public class Trigger
{
public enum Trigger_Enum {
pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, deviceOrientation, profileActive, screenState, musicPlaying, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
switch(this)
{
case pointOfInterest:
return context.getResources().getString(R.string.triggerPointOfInterest);
case timeFrame:
return context.getResources().getString(R.string.triggerTimeFrame);
case charging:
return context.getResources().getString(R.string.triggerCharging);
case batteryLevel:
return context.getResources().getString(R.string.batteryLevel);
case usb_host_connection:
return context.getResources().getString(R.string.triggerUsb_host_connection);
case speed:
return context.getResources().getString(R.string.triggerSpeed);
case noiseLevel:
return context.getResources().getString(R.string.triggerNoiseLevel);
case wifiConnection:
return context.getResources().getString(R.string.wifiConnection);
case process_started_stopped:
return context.getResources().getString(R.string.anotherAppIsRunning);
case airplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case roaming:
return context.getResources().getString(R.string.roaming);
case phoneCall:
return context.getResources().getString(R.string.phoneCall);
case nfcTag:
return context.getResources().getString(R.string.nfcTag);
case activityDetection:
return context.getResources().getString(R.string.activityDetection);
case bluetoothConnection:
return context.getResources().getString(R.string.bluetoothConnection);
case headsetPlugged:
return context.getResources().getString(R.string.triggerHeadsetPlugged);
case notification:
return context.getResources().getString(R.string.notification);
case deviceOrientation:
return context.getResources().getString(R.string.deviceOrientation);
case profileActive:
return context.getResources().getString(R.string.profile);
case musicPlaying:
return context.getResources().getString(R.string.musicPlaying);
case screenState:
return context.getResources().getString(R.string.screenState);
default:
return "Unknown";
}
}
};
Rule parentRule = null;
Calendar lastTimeNotApplied = null;
@ -123,6 +182,14 @@ public class Trigger
if(!checkProfileActive())
result = false;
break;
case musicPlaying:
if(!checkMusicPlaying())
result = false;
break;
case screenState:
if(!checkScreenState())
result = false;
break;
default:
break;
}
@ -271,6 +338,11 @@ public class Trigger
return true;
}
boolean checkMusicPlaying()
{
return triggerParameter == MediaPlayerListener.isAudioPlaying(Miscellaneous.getAnyContext());
}
boolean checkProfileActive()
{
String demandedProfileName = getTriggerParameter2().split(Trigger.triggerParameter2Split)[0];
@ -308,6 +380,23 @@ public class Trigger
return false;
}
boolean checkScreenState()
{
try
{
int desiredState = Integer.parseInt(getTriggerParameter2());
int currentState = ScreenStateReceiver.getScreenState();
return desiredState == currentState;
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Trigger", "Error checking profile trigger.", 4);
}
return false;
}
boolean checkDeviceOrientation()
{
String deviceOrientationPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
@ -532,7 +621,19 @@ public class Trigger
boolean checkProcess()
{
boolean running = ProcessListener.getRunningApps().contains(this.getProcessName());
boolean running = false;
if(getTriggerParameter2().contains(triggerParameter2Split))
{
String parts[] = triggerParameter2.split(triggerParameter2Split);
for(String appName : ProcessListener.getRunningApps())
{
if(appName.startsWith(parts[0]))
running = true;
}
}
else
running = ProcessListener.getRunningApps().contains(this.getProcessName());
if(running)
Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is currently running.", 4);
@ -938,8 +1039,6 @@ public class Trigger
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
// if(this.applies(null))
// {
// If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1);
@ -950,15 +1049,7 @@ public class Trigger
Calendar calSchedule = Calendar.getInstance();
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
/*
* 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.
*/
// if(trigger.checkDateTime(calSchedule.getTime(), false))
// {
return calSchedule;
// }
// }
}
else
Miscellaneous.logEvent("i", "Trigger", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
@ -991,73 +1082,14 @@ public class Trigger
return false;
}
/*
* Can be several things:
* -PointOfInterest
* -TimeFrame
* -Event (like charging, cable plugged, etc.)
*/
public enum Trigger_Enum {
pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, deviceOrientation, profileActive, screenState, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
switch(this)
{
case pointOfInterest:
return context.getResources().getString(R.string.triggerPointOfInterest);
case timeFrame:
return context.getResources().getString(R.string.triggerTimeFrame);
case charging:
return context.getResources().getString(R.string.triggerCharging);
case batteryLevel:
return context.getResources().getString(R.string.batteryLevel);
case usb_host_connection:
return context.getResources().getString(R.string.triggerUsb_host_connection);
case speed:
return context.getResources().getString(R.string.triggerSpeed);
case noiseLevel:
return context.getResources().getString(R.string.triggerNoiseLevel);
case wifiConnection:
return context.getResources().getString(R.string.wifiConnection);
case process_started_stopped:
return context.getResources().getString(R.string.anotherAppIsRunning);
case airplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case roaming:
return context.getResources().getString(R.string.roaming);
case phoneCall:
return context.getResources().getString(R.string.phoneCall);
case nfcTag:
return context.getResources().getString(R.string.nfcTag);
case activityDetection:
return context.getResources().getString(R.string.activityDetection);
case bluetoothConnection:
return context.getResources().getString(R.string.bluetoothConnection);
case headsetPlugged:
return context.getResources().getString(R.string.triggerHeadsetPlugged);
case notification:
return context.getResources().getString(R.string.notification);
case deviceOrientation:
return context.getResources().getString(R.string.deviceOrientation);
case profileActive:
return context.getResources().getString(R.string.profile);
default:
return "Unknown";
}
}
};
private boolean triggerParameter; //if true->started event, if false->stopped
private String triggerParameter2;
boolean triggerParameter; //if true->started event, if false->stopped
String triggerParameter2;
public static final String triggerParameter2Split = "tp2split";
private Trigger_Enum triggerType = null;
private PointOfInterest pointOfInterest = null;
private TimeFrame timeFrame;
Trigger_Enum triggerType = null;
PointOfInterest pointOfInterest = null;
TimeFrame timeFrame;
public static String triggerPhoneCallStateRinging = "ringing";
public static String triggerPhoneCallStateStarted = "started";
@ -1067,17 +1099,17 @@ public class Trigger
public static String triggerPhoneCallDirectionAny = "any";
public static String triggerPhoneCallNumberAny = "any";
private double speed; //km/h
private long noiseLevelDb;
private String processName = null;
private int batteryLevel;
private int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
private String phoneNumber = null;
private String nfcTagId = null;
private String bluetoothEvent = null;
private String bluetoothDeviceAddress = null;
private int activityDetectionType = -1;
private int headphoneType = -1;
double speed; //km/h
long noiseLevelDb;
String processName = null;
int batteryLevel;
int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
String phoneNumber = null;
String nfcTagId = null;
String bluetoothEvent = null;
String bluetoothDeviceAddress = null;
int activityDetectionType = -1;
int headphoneType = -1;
public int getHeadphoneType()
{
@ -1492,6 +1524,31 @@ public class Trigger
else
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.profileNotActive), getTriggerParameter2().split(Trigger.triggerParameter2Split)[0]));
break;
case musicPlaying:
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getString(R.string.musicIsPlaying));
else
returnString.append(Miscellaneous.getAnyContext().getString(R.string.musicIsNotPlaying));
break;
case screenState:
String state;
switch(triggerParameter2)
{
case "0":
state = Miscellaneous.getAnyContext().getString(R.string.off);
break;
case "1":
state = Miscellaneous.getAnyContext().getString(R.string.on);
break;
case "2":
state = Miscellaneous.getAnyContext().getString(R.string.unlocked);
break;
default:
state = Miscellaneous.getAnyContext().getString(R.string.unknown);
}
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.screenIs), state));
break;
default:
returnString.append("error");
break;
@ -1544,11 +1601,7 @@ public class Trigger
public static String[] getTriggerTypesAsArray()
{
ArrayList<String> triggerTypesList = new ArrayList<String>();
/*for(int i=0; i<Trigger_Enum.values().length; i++)
{
triggerTypesList.add(Trigger_Enum.values()[i].toString());
}*/
for(Trigger_Enum triggerType : Trigger_Enum.values())
triggerTypesList.add(triggerType.name());

View File

@ -263,11 +263,9 @@ public class XmlFileInterface
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.wifiConnection)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerParameter2());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.process_started_stopped)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getProcessName());
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerParameter2());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.batteryLevel)
serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getBatteryLevel()));
// else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.phoneCall)
// serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getPhoneDirection()) + "," + String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getPhoneNumber()));
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.nfcTag)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getNfcTagId());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.activityDetection)
@ -943,8 +941,16 @@ public class XmlFileInterface
}
else if(newTrigger.getTriggerType() == Trigger_Enum.process_started_stopped)
{
newTrigger.setProcessName(triggerParameter2);
newTrigger.setTriggerParameter2(triggerParameter2);
if(triggerParameter2.contains(triggerParameter2Split))
{
String[] parts = triggerParameter2.split(triggerParameter2Split);
newTrigger.setProcessName(parts[1]);
}
else
newTrigger.setProcessName(triggerParameter2);
}
else if(newTrigger.getTriggerType() == Trigger_Enum.phoneCall)
{
@ -1154,12 +1160,17 @@ public class XmlFileInterface
newAction.setAction(Action_Enum.disableScreenRotation);
else if(actionNameString.equals("disableScreenRotation"))
newAction.setAction(Action_Enum.disableScreenRotation);
else if(actionNameString.equals("playMusic"))
{
newAction.setAction(Action_Enum.controlMediaPlayback);
newAction.setParameter2("1");
}
else if(actionNameString.equals("wakeupDevice"))
{
newAction.setAction(Action_Enum.turnScreenOnOrOff);
newAction.setParameter1(true);
}
// *** deprecated
// *** :deprecated
else
newAction.setAction(Action_Enum.valueOf(actionNameString));
@ -1273,14 +1284,14 @@ public class XmlFileInterface
{
String newTag;
if(tag.contains(Action.intentPairSeperator)) // already has new format
if(tag.contains(Action.intentPairSeparator)) // already has new format
newTag = tag;
else
newTag = tag.replace("/", Action.intentPairSeperator);
newTag = tag.replace("/", Action.intentPairSeparator);
String[] newTagPieces = newTag.split(";");
if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeperator)))
if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeparator)))
{
newTag = Actions.dummyPackageString + ";" + newTag;
newTagPieces = newTag.split(";");
@ -1290,7 +1301,7 @@ public class XmlFileInterface
newTag += ";" + ActivityManageActionStartActivity.startByActivityString;
else if(newTagPieces.length >= 3)
{
if(newTagPieces[2].contains(Action.intentPairSeperator))
if(newTagPieces[2].contains(Action.intentPairSeparator))
newTag = newTagPieces[0] + ";" + newTagPieces[1] + ";" + ActivityManageActionStartActivity.startByActivityString + ";" + newTagPieces[2];
}

View File

@ -162,7 +162,7 @@ public class LocationProvider
(
(locationList.get(i).getProvider().equals(LocationManager.GPS_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyGps)
||
(locationList.get(i).getProvider().equals(LocationManager.NETWORK_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyNetwork)
(locationList.get(i).getProvider().equals(LocationManager.NETWORK_PROVIDER) && locationList.get(i).getAccuracy() > Settings.satisfactoryAccuracyNetwork)
)
{
Miscellaneous.logEvent("i", "Speed", "Not using 2 most recent locations for speed calculation because at least one does not have a satisfactory accuracy: " + locationList.get(i).toString(), 4);
@ -189,7 +189,7 @@ public class LocationProvider
/*
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);
else
{
@ -232,12 +232,6 @@ public class LocationProvider
public void startLocationService()
{
// if(Settings.useAccelerometerForPositioning && !Miscellaneous.isAndroidEmulator())
// {
// accelerometerHandler = new AccelerometerHandler();
// mySensorActivity = new SensorActivity(this);
// }
// startPhoneStateListener
PhoneStatusListener.startPhoneStatusListener(parentService); // also used to mute anouncements during calls
@ -246,10 +240,8 @@ public class LocationProvider
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))
{
// TelephonyManager telephonyManager = (TelephonyManager) AutomationService.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
// startCellLocationChangedReceiver
if (CellLocationChangedReceiver.isCellLocationChangedReceiverPossible())
{
@ -432,7 +424,7 @@ public class LocationProvider
}
// *********** 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);
if(CellLocationChangedReceiver.haveAllPermission())
@ -514,7 +506,6 @@ public class LocationProvider
Message msg = new Message();
msg.what = 1;
speedHandler.sendMessageAtTime(msg, timeOfForcedLocationCheck.getTimeInMillis());
// speedHandler.sendMessageDelayed(msg, delayTime);
speedTimerActive = true;
}
else
@ -531,7 +522,7 @@ public class LocationProvider
if(msg.what == 1)
{
// time is up, no cell location updates since x minutes, start accelerometer
String text = "Timer triggered. Based on the last location and speed we may be at a POI. Forcing location update in case CellLocationChangedReceiver didn\'t fire.";
Miscellaneous.logEvent("i", "LocationProvider", "Timer triggered. Based on the last location and speed we may be at a POI. Forcing location update in case CellLocationChangedReceiver didn\'t fire.", 5);
Location currentLocation = CellLocationChangedReceiver.getInstance().getLocation("coarse");
AutomationService.getInstance().getLocationProvider().setCurrentLocation(currentLocation, false);

View File

@ -0,0 +1,105 @@
package com.jens.automation2.receivers;
import android.content.Context;
import android.media.AudioManager;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Settings;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
public class MediaPlayerListener implements AutomationListenerInterface
{
static MediaPlayerListener instance = null;
static AudioManager mAudioManager = null;
static boolean listenerActive = false;
Timer timer = null;
TimerTask task = null;
public static boolean isAudioPlaying(Context context)
{
if(mAudioManager == null)
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
return mAudioManager.isMusicActive();
}
public static MediaPlayerListener getInstance()
{
if(instance == null)
instance = new MediaPlayerListener();
return instance;
}
@Override
public void startListener(AutomationService automationService)
{
Miscellaneous.logEvent("i", "MediaPlayerListener", "Starting listener.",5);
if(!listenerActive)
{
if(timer == null)
{
timer = new Timer();
}
else
{
task.cancel();
timer.purge();
}
task = new TimerTask()
{
@Override
public void run()
{
synchronized(this)
{
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.musicPlaying);
for (int i = 0; i < ruleCandidates.size(); i++)
{
if (ruleCandidates.get(i).getsGreenLight(AutomationService.getInstance()))
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
}
}
}
};
timer.scheduleAtFixedRate(task, 0, Settings.musicCheckFrequency);
}
}
@Override
public void stopListener(AutomationService automationService)
{
Miscellaneous.logEvent("i", "MediaPlayerListener", "Stopping listener.",5);
if(listenerActive)
{
if (timer != null)
{
timer.cancel();
timer.purge();
}
}
}
@Override
public boolean isListenerRunning()
{
return listenerActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[] { Trigger.Trigger_Enum.musicPlaying };
}
}

View File

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

View File

@ -1,5 +1,6 @@
package com.jens.automation2.receivers;
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
@ -8,6 +9,7 @@ import android.content.Context;
import android.os.Handler;
import android.os.Message;
import com.jens.automation2.Action;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
@ -208,12 +210,12 @@ public class ProcessListener implements AutomationListenerInterface
workHandler.sendMessage(answer);
//activate rule(s)
/*ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByProcess();
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.process_started_stopped);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).applies(automationService))
ruleCandidates.get(i).activate(automationService);
}*/
if(ruleCandidates.get(i).getsGreenLight(automationService))
ruleCandidates.get(i).activate(automationService, false);
}
isMonitoringActive = false;
@ -231,6 +233,7 @@ public class ProcessListener implements AutomationListenerInterface
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE);
final List<RunningAppProcessInfo> apps = activityManager.getRunningAppProcesses();
ArrayList<String> runningAppsListReference;
if(lastWritten == 1)
@ -246,32 +249,23 @@ public class ProcessListener implements AutomationListenerInterface
runningAppsListReference.clear();
for (int i = 0; i < services.size(); i++)
/*for (int i = 0; i < services.size(); i++)
{
if(!runningAppsListReference.contains(services.get(i).baseActivity.getClassName()))
{
// you may broadcast a new application launch here.
runningAppsListReference.add(services.get(i).baseActivity.getClassName());
}
}
}*/
for (int i = 0; i < apps.size(); i++)
{
if(!runningAppsListReference.contains(apps.get(i).processName))
{
// you may broadcast a new application launch here.
runningAppsListReference.add(apps.get(i).processName);
}
}
// for(String runningApp : runningAppsListReference)
// {
// Miscellaneous.logEvent("i", "Running app", runningApp, 5);
// }
// List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
// for(int i = 0; i < procInfos.size(); i++)
// {
// ArrayList<String> runningPkgs = new ArrayList<String>(Arrays.asList(procInfos.get(i).pkgList));
//
// Collection diff = subtractSets(runningPkgs, stalkList);
//
// if(diff != null)
// {
// stalkList.removeAll(diff);
// }
// }
// Set marker to the one to be written next.
if(lastWritten == 1)
@ -351,7 +345,7 @@ public class ProcessListener implements AutomationListenerInterface
return false;
}
private boolean checkifThisIsActive(RunningAppProcessInfo target)
private boolean checkIfThisIsActive(RunningAppProcessInfo target)
{
boolean result = false;
RunningTaskInfo info;
@ -397,7 +391,6 @@ public class ProcessListener implements AutomationListenerInterface
Message message = new Message();
message.arg1 = 1;
// schedulingHandler.sendMessageDelayed(message, Settings.timeBetweenNoiseLevelMeasurements * 1000);
schedulingHandler.sendMessageDelayed(message, 10000);
}
else
@ -444,7 +437,7 @@ public class ProcessListener implements AutomationListenerInterface
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission("android.permission.GET_TASKS", Miscellaneous.getAnyContext());
return ActivityPermissions.havePermission(Manifest.permission.GET_TASKS, Miscellaneous.getAnyContext());
}
@Override
@ -458,6 +451,4 @@ public class ProcessListener implements AutomationListenerInterface
{
return new Trigger_Enum[] { Trigger_Enum.process_started_stopped };
}
}
}

View File

@ -0,0 +1,162 @@
package com.jens.automation2.receivers;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.util.ArrayList;
public class ScreenStateReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
static int screenState = -1; // initialize with a better value than this
public static AutomationService automationServiceRef = null;
private static boolean screenStateReceiverActive = false;
private static IntentFilter screenStateIntentFilter = null;
private static Intent screenStatusIntent = null;
private static BroadcastReceiver screenStateReceiverInstance = null;
public static BroadcastReceiver getScreenStateReceiverInstance()
{
if(screenStateReceiverInstance == null)
screenStateReceiverInstance = new ScreenStateReceiver();
return screenStateReceiverInstance;
}
public static void startScreenStateReceiver(final AutomationService automationServiceRef)
{
if(!screenStateReceiverActive)
{
ScreenStateReceiver.automationServiceRef = automationServiceRef;
if(screenStateReceiverInstance == null)
screenStateReceiverInstance = new ScreenStateReceiver();
if(screenStateIntentFilter == null)
{
screenStateIntentFilter = new IntentFilter();
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
screenStateIntentFilter.addAction(Intent.ACTION_USER_PRESENT);
// Intent.ACTION_USER_UNLOCKED
}
screenStatusIntent = automationServiceRef.registerReceiver(screenStateReceiverInstance, screenStateIntentFilter);
screenStateReceiverActive = true;
}
}
public static void stopScreenStateReceiver()
{
if(screenStateReceiverActive)
{
if(screenStateReceiverInstance != null)
{
automationServiceRef.unregisterReceiver(screenStateReceiverInstance);
screenStateReceiverInstance = null;
}
screenStateReceiverActive = false;
}
}
public static boolean isScreenStateReceiverActive()
{
return screenStateReceiverActive;
}
public static int getScreenState()
{
return screenState;
}
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
public static int getCurrentChargingState()
{
return currentChargingState;
}
@Override
public void onReceive(Context context, Intent intent)
{
if (intent == null)
return;
if (context == null)
return;
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Received: " + intent.getAction(), 3);
try
{
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
ScreenStateReceiver.screenState = 0;
}
else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
ScreenStateReceiver.screenState = 1;
}
else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT))
{
ScreenStateReceiver.screenState = 2;
}
else
{
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Unknown state received: " + intent.getAction(), 3);
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Error receiving screen state: " + e.getMessage(), 3);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.screenState);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
@Override
public void startListener(AutomationService automationService)
{
ScreenStateReceiver.startScreenStateReceiver(automationService);
}
@Override
public void stopListener(AutomationService automationService)
{
ScreenStateReceiver.stopScreenStateReceiver();
}
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission(Manifest.permission.READ_PHONE_STATE, Miscellaneous.getAnyContext()) &&
ActivityPermissions.havePermission(Manifest.permission.BATTERY_STATS, Miscellaneous.getAnyContext());
}
@Override
public boolean isListenerRunning()
{
return ScreenStateReceiver.isScreenStateReceiverActive();
}
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger_Enum[] { Trigger_Enum.screenState };
}
}

View File

@ -1,292 +0,0 @@
package com.jens.automation2.receivers;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.util.ArrayList;
public class ScreenStatusReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
static int batteryLevel = -1; // initialize with a better value than this
public static AutomationService automationServiceRef = null;
private static boolean usbHostConnected = false;
private static boolean screenStateReceiverActive = false;
private static IntentFilter screenStateIntentFilter = null;
private static Intent screenStatusIntent = null;
private static BroadcastReceiver screenStateReceiverInstance = null;
public static void startScreenStateReceiver(final AutomationService automationServiceRef)
{
if(!screenStateReceiverActive)
{
ScreenStatusReceiver.automationServiceRef = automationServiceRef;
if(screenStateReceiverInstance == null)
screenStateReceiverInstance = new ScreenStatusReceiver();
if(screenStateIntentFilter == null)
{
screenStateIntentFilter = new IntentFilter();
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
}
screenStatusIntent = automationServiceRef.registerReceiver(screenStateReceiverInstance, screenStateIntentFilter);
screenStateReceiverActive = true;
}
}
public static void stopScreenStateReceiver()
{
if(screenStateReceiverActive)
{
if(screenStateReceiverInstance != null)
{
automationServiceRef.unregisterReceiver(screenStateReceiverInstance);
screenStateReceiverInstance = null;
}
screenStateReceiverActive = false;
}
}
public static boolean isScreenStateReceiverActive()
{
return screenStateReceiverActive;
}
public static boolean isUsbHostConnected()
{
return usbHostConnected;
}
public static int getBatteryLevel()
{
return batteryLevel;
}
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
public static int getCurrentChargingState()
{
return currentChargingState;
}
@Override
public void onReceive(Context context, Intent intent)
{
// Log.i("Battery", "Some battery event");
if (intent == null)
return;
if (context == null)
return;
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW))
{
Log.i("Battery", "Low battery event");
}
else
{
try
{
// Miscellaneous.logEvent("i", "BatteryReceiver", "Received battery event.");
// if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED))
// {
batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
// int scale = -1;
// int voltage = -1;
// int temp = -1;
// scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
// temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
// voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
Log.i("Battery", "Level: " + String.valueOf(batteryLevel));
this.actionBatteryLevel(context);
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int statusPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
// Miscellaneous.logEvent("i", "BatteryReceiver", "Status: " + String.valueOf(statusPlugged));
switch(statusPlugged)
{
case BatteryManager.BATTERY_PLUGGED_AC:
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
// Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.");
this.actionCharging(context);
break;
case BatteryManager.BATTERY_PLUGGED_USB:
this.actionUsbConnected(context);
break;
}
switch(status)
{
// case BatteryManager.BATTERY_STATUS_CHARGING:
// break;
case BatteryManager.BATTERY_STATUS_FULL:
// Toast.makeText(context, "Regular charging full", Toast.LENGTH_LONG).show();
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.");
this.actionCharging(context);
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
this.actionDischarging(context);
break;
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "BatteryReceiver", "Error receiving battery status: " + e.getMessage(), 3);
}
}
}
public static int isDeviceCharging(Context context)
{
switch(currentChargingState)
{
case 0:
Miscellaneous.logEvent("w", "ChargingInfo", "Status of device charging was requested. Information isn't available, yet.", 4);
break;
case 1:
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is discharging.", 3);
break;
case BatteryManager.BATTERY_STATUS_CHARGING:
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is charging.", 3);
break;
}
return currentChargingState;
}
private void actionCharging(Context context)
{
if(currentChargingState != BatteryManager.BATTERY_STATUS_CHARGING) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.", 3);
currentChargingState = BatteryManager.BATTERY_STATUS_CHARGING;
//activate rule(s)
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
}
private void actionBatteryLevel(Context context)
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery level has changed.", 3);
//activate rule(s)
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.batteryLevel);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
private void actionDischarging(Context context)
{
if(currentChargingState != BatteryManager.BATTERY_STATUS_UNKNOWN) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is discharging.", 3);
currentChargingState = BatteryManager.BATTERY_STATUS_UNKNOWN;
//activate rule(s)
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(false);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
this.actionUsbDisconnected(context);
}
}
private void actionUsbConnected(Context context)
{
// Event usbConnected
// Miscellaneous.logEvent("i", "BatteryReceiver", "BATTERY_PLUGGED_USB");
if(!usbHostConnected)
{
usbHostConnected = true;
Miscellaneous.logEvent("i", "BatteryReceiver", "Connected to computer.", 3);
Toast.makeText(context, "Connected to computer.", Toast.LENGTH_LONG).show();
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.usb_host_connection);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(true);
for(Rule oneRule : ruleCandidates)
{
if(oneRule.getsGreenLight(context))
oneRule.activate(automationServiceRef, false);
}
this.actionCharging(context);
}
}
private void actionUsbDisconnected(Context context)
{
// Event usbDisConnected
if(usbHostConnected)
{
usbHostConnected = false;
Miscellaneous.logEvent("i", "BatteryReceiver", "Disconnected from computer.", 3);
Toast.makeText(context, "Disconnected from computer.", Toast.LENGTH_LONG).show();
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.usb_host_connection);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(false);
for(Rule oneRule : ruleCandidates)
{
if(oneRule.getsGreenLight(context))
oneRule.activate(automationServiceRef, false);
}
}
}
@Override
public void startListener(AutomationService automationService)
{
ScreenStatusReceiver.startScreenStateReceiver(automationService);
}
@Override
public void stopListener(AutomationService automationService)
{
ScreenStatusReceiver.stopScreenStateReceiver();
}
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission(Manifest.permission.READ_PHONE_STATE, Miscellaneous.getAnyContext()) &&
ActivityPermissions.havePermission(Manifest.permission.BATTERY_STATS, Miscellaneous.getAnyContext());
}
@Override
public boolean isListenerRunning()
{
return ScreenStatusReceiver.isScreenStateReceiverActive();
}
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger_Enum[] { Trigger_Enum.screenState };
}
}

View File

@ -17,7 +17,7 @@ public class StartupIntentReceiver extends BroadcastReceiver
{
Settings.readFromPersistentStorage(context);
Miscellaneous.logEvent("i", "Boot event", "Received event: " + intent.getAction(), 5);
// Miscellaneous.logEvent("i", "Boot event", "Received event: " + intent.getAction(), 5);
if(Settings.startServiceAtSystemBoot)
{

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/actionMediaControl" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/actionMediaControlNotice" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbMediaPlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/playPause" />
<RadioButton
android:id="@+id/rbMediaPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/play" />
<RadioButton
android:id="@+id/rbMediaPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pause" />
<RadioButton
android:id="@+id/rbMediaStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop" />
<RadioButton
android:id="@+id/rbMediaPrevious"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/previous" />
<RadioButton
android:id="@+id/rbMediaNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next" />
</RadioGroup>
<Button
android:id="@+id/bSaveControlMediaAction"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -46,7 +46,7 @@
android:orientation="horizontal" >
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/latitude"

View File

@ -23,7 +23,7 @@
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/end"

View File

@ -292,6 +292,18 @@
android:inputType="number"></EditTextPreference>
</PreferenceCategory>
<PreferenceCategory
android:summary="@string/musicPlayingDetection"
android:title="@string/musicPlayingDetection">
<EditTextPreference
android:key="musicCheckFrequency"
android:summary="@string/musicCheckFrequencySummary"
android:title="@string/musicCheckFrequencyTitle"
android:inputType="number"></EditTextPreference>
</PreferenceCategory>
</PreferenceScreen>

View File

@ -151,7 +151,7 @@
android:orientation="vertical"
android:layout_margin="10dp" >
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helpTextTimeFrame" />

View File

@ -193,7 +193,7 @@
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="0dip"
android:layout_weight="5"
android:layout_height="wrap_content"
@ -203,6 +203,34 @@
android:singleLine="false"
android:textSize="20dp" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="20dp" >
<TextView
android:layout_width="0dip"
android:layout_weight="5"
android:layout_height="wrap_content"
android:gravity="right"
android:text="@string/lastProfile"
android:scrollHorizontally="false"
android:singleLine="false"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvLastProfile"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="5"
android:scrollHorizontally="false"
android:singleLine="false"
android:text="n./a."
android:textSize="20dp" />
</TableRow>
<TableRow
android:layout_width="fill_parent"

View File

@ -51,7 +51,7 @@
android:background="@color/barBackgroundColor" >
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ruleList"

View File

@ -11,7 +11,7 @@
<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="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="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>
@ -669,4 +669,35 @@
<string name="notificationCloseActionExplanation">Wenn Sie keine Kriterien angeben, werden ALLE Benachrichtigungen geschlossen. Es wird also empfohlen, zumindest eine Anwendung zu spezifizieren und/oder Titel oder Text anzugeben.</string>
<string name="profileWarning">Die Einstellungen, die Sie hier vornehmen, können dazu führen, dass Sie bestimmte Dinge auf Ihrem Telefon nicht mehr mitbekommen. Sie können sogar Ihren Wecker zum Schweigen bringen. Was auch immer Sie hier einstellen - es wird empfohlen, es zu testen.</string>
<string name="ifString">falls</string>
<string name="pleaseSelectActionValue">Bitte wählen Sie eine Aktion!</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Medien steuern</string>
<string name="play">abspielen</string>
<string name="stop">stop</string>
<string name="next">nächster</string>
<string name="previous">vorheriger</string>
<string name="pause">pausieren</string>
<string name="playPause">abspielen/pause umschalten</string>
<string name="selectCommand">Kommando auswählen</string>
<string name="unlocked">entsperrt</string>
<string name="on">an</string>
<string name="off">aus</string>
<string name="actionMediaControlNotice">Bedenken Sie, daß diese Aktion nicht notwendigerweise mit allen Playern funktioniert. Und selbst, wenn es mit einem grundsätzlich funktioniert, müssen auch nicht alle der u.g. Kommandos funktionieren.</string>
<string name="screenState">Bildschirm Status</string>
<string name="actionMediaControl">Medien steuern</string>
<string name="selectDesiredState">Bitte gewünschten Zustand wählen</string>
<string name="screenIs">Bildschirm ist %1$s</string>
<string name="sendEmailToDev">Email an Entwickler schicken</string>
<string name="controlCenter">Steuerungszentrale</string>
<string name="emailContactNotice">Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Aufgrund Google\'s unendlicher Weisheit, ist die letzte Android Version, mit der diese Funktion noch funktioniert, die Version %1$s. Sie können es hier einrichten, aber vermutlich wird es keine Auswirkung haben.</string>
<string name="musicPlaying">Musik läuft</string>
<string name="selectParameters">Wählen Sie die Parameter</string>
<string name="musicIsPlaying">Musik läuift</string>
<string name="musicIsNotPlaying">Musik läuft nicht</string>
<string name="musicCheckFrequencyTitle">Prüffrequenz</string>
<string name="musicCheckFrequencySummary">Millisekunden zwischen Prüfungen</string>
<string name="musicPlayingDetection">Musik-läuft Erkennung</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="lastProfile">Letztes Profil:</string>
</resources>

View File

@ -668,4 +668,35 @@
<string name="comparisonCaseInsensitive">Las comparaciones se realizan sin distinción de mayúsculas y minúsculas</string>
<string name="profileWarning">La configuración que realice aquí puede hacer que ya no note ciertas cosas de su teléfono. Incluso puede silenciar su alarma de despertar. Así que hagas lo que hagas, se recomienda que lo pruebes.</string>
<string name="ifString">si</string>
<string name="on">encendido</string>
<string name="off">apagado</string>
<string name="unlocked">desbloqueado</string>
<string name="play">reproducir</string>
<string name="pause">pausar</string>
<string name="previous">ultimo</string>
<string name="next">proximo</string>
<string name="stop">parar</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Controlar la reproducción de medios</string>
<string name="actionMediaControl">Controlar la reproducción de medios</string>
<string name="pleaseSelectActionValue">Por favor elije una acción!</string>
<string name="playPause">alternar reproducir/pausar</string>
<string name="selectCommand">Elije el comando</string>
<string name="screenState">Estado de la pantalla</string>
<string name="selectDesiredState">Elije el estado deseado</string>
<string name="controlCenter">Centro de control</string>
<string name="screenIs">pantalla esta %1$s</string>
<string name="sendEmailToDev">Enviar email al desrollador</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Debido a la infinita sabiduría de Google, la última versión de Android en la que se sabe que funciona esta función es %1$s. Puede configurarlo, pero probablemente no tendrá ningún efecto.</string>
<string name="emailContactNotice">El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.</string>
<string name="actionMediaControlNotice">Ten en cuenta que esta acción puede no funcionar con TODOS los jugadores. E incluso si lo hace, no todos los botones funcionan necesariamente.</string>
<string name="musicPlaying">Musica esta reproduciendo</string>
<string name="selectParameters">Elije parametros</string>
<string name="musicIsPlaying">musica esta reproduciendo</string>
<string name="musicIsNotPlaying">musica no esta reproduciendo</string>
<string name="musicCheckFrequencyTitle">Frecuencia de los controles</string>
<string name="musicCheckFrequencySummary">Millisegundos entre controles</string>
<string name="musicPlayingDetection">Musica tocando deteción</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="lastProfile">Último perfil:</string>
</resources>

View File

@ -456,10 +456,10 @@
<string name="settingsSetToDefault">Impostazioni predefinite ripristinate.</string>
<string name="settingsWillTakeTime">Alcune impostazioni non saranno applicate prima che alcune impostazioni contestuali cambino o che il servizio venga riavviato.</string>
<string name="shareConfigAndLogExplanation">Questo creerà una email con la tua configurazione e i file di log allegati come file zip. Non sarà inviata automaticamente, dovrai premere \"invia\". Puoi anche cambiare il destinatario con te stesso, per esempio.</string>
<string name="shareConfigAndLogFilesWithDev">Agganciare i file di configurazione e di registro</string>
<string name="shareConfigAndLogFilesWithDev">Allegare i file di configurazione e di registro</string>
<string name="showHelp">Mostra Aiuto</string>
<string name="showIcon">Mostra icona</string>
<string name="showIconWhenServiceIsRunning">Mostra una icona quando il servizio è attivo (nasconderla funziona solo in versioni inferiori ad Android 7). Se hai una versione superiore, vai alle impostazioni di sistema, quindi all\'automazione, quindi alle notifiche e disabilita la \"Service notification\".</string>
<string name="showIconWhenServiceIsRunning">Mostra una icona quando il servizio è attivo (nasconderla funziona solo in versioni inferiori ad Android 7). Se hai una versione superiore, vai alle impostazioni di sistema, quindi Automation, e poi seleziona Notifiche, dove potrai disabilitare la \"Service notification\".</string>
<string name="showOnMap">Mostra sulla mappa</string>
<string name="someOptionsNotAvailableYet">Alcune opzioni sono disabilitate in quanto non ancora implementate. Saranno introdotte in una versione successiva.</string>
<string name="soundMode">Modalità sonora</string>
@ -533,7 +533,7 @@
<string name="tuesday">Martedì</string>
<string name="unknownError">Errore indeterminato.</string>
<string name="until">finchè</string>
<string name="urlLegend">Variabili:\n È possibile utilizzare le seguenti variabili. All\'attivazione saranno sostituite con il valore corrispondente sul dispositivo. Includi le parentesi nel tuo testo.\n\n[uniqueid] - Il numero di serie del tuo dispositivo\n[serialnr] - Il serial number del tuo dispositivio (&lt; Android 9)\n[latitude] - La latitudine del tuo dispositivo\n[longitude] - La longitudine del tuo dispositivo\n[phonenr] - Numero dell\'ultima chiamata (entrante o uscente)\n[d] - Il giorno del mese, sempre 2 cifre\n[m] - Mese in formato numerico, sempre 2 cifre\n[Y] - L\anno, sempre 4 cifre\n[h] - Ore in formato 12 ore, sempre 2 cifre con due punti\n[H] - Ore in formato 24 ore, sempre 2 cifre con due punti\n[i] - Minuti, sempre 2 cifre\n[s] - Secondi, sempre 2 cifre\n[ms] - millisecondi, sempre 3 cifre [notificationTitle] - titolo dell\'ultima notifica [notificationText] - testo dell\'ultima notifica</string>
<string name="urlLegend">Variabili:\n È possibile utilizzare le seguenti variabili. Quando attivate, saranno sostituite con il valore corrispondente sul tuo dispositivo. Includi le parentesi nel tuo testo.\n\n[uniqueid] - L\'ID unico del tuo dispositivo\n[serialnr] - Il numero di serie del tuo dispositivio (&lt; Android 9)\n[latitude] - La latitudine del tuo dispositivo\n[longitude] - La longitudine del tuo dispositivo\n[phonenr] - Numero dell\'ultima chiamata (entrante o uscente)\n[d] - Il giorno del mese, sempre 2 cifre con zero iniziale \n[m] - Mese in formato numerico, sempre 2 cifre con zero iniziale \n[Y] - L\anno, sempre con 4 cifre\n[h] - Ore in formato 12 ore, sempre 2 cifre con due punti\n[H] - Ore in formato 24 ore, sempre 2 cifre con due punti\n[i] - Minuti, sempre 2 cifre\n[s] - Secondi, sempre 2 cifre\n[ms] - millisecondi, sempre 3 cifre\n[notificationTitle] - titolo dell\'ultima notifica\n[notificationText] - testo dell\'ultima notifica</string>
<string name="urlToTrigger">URL da caricare:</string>
<string name="urlTooShort">L\'url deve avere almeno 10 caratteri.</string>
<string name="usbTetheringFailForAboveGingerbread">Questo molto probabilmente non funzionerà dato che sei su una versione superiore ad Android 2.3. Tuttavia è possibile utilizzare la connessione wifi tethering per attivare la regola.</string>
@ -661,12 +661,43 @@
<string name="launcherNotFound">Impossibile identificare un\'attività di avvio di questa app. Dovrai sceglierne uno manualmente.</string>
<string name="createNotification">Crea notifica</string>
<string name="enterTitle">Inserisci un titolo.</string>
<string name="enterText">Immettere un testo.</string>
<string name="info">Info</string>
<string name="enterText">Aggiungi un testo.</string>
<string name="info">Informazioni</string>
<string name="profileWasNotFound">Il profilo utilizzato in questa regola non sembra più esistere. Il primo in ordine alfabetico è stato selezionato.</string>
<string name="comparisonCaseInsensitive">I confronti sono fatti caso-INsensitive</string>
<string name="comparisonCaseInsensitive">I confronti non distinguono fra maiuscole e minuscole</string>
<string name="closeNotifications">Chiudi notifica(e)</string>
<string name="notificationCloseActionExplanation">Se non specifichi alcun criterio, questa azione chiuderà TUTTE le notifiche. Quindi si consiglia di specificare almeno i criteri per almeno 1 di applicazione, titolo o testo.</string>
<string name="profileWarning">Le impostazioni che fai qui possono far sì che tu non noti più certe cose dal tuo telefono. Possono anche mettere a tacere la sveglia. Quindi, qualunque cosa tu faccia, ti consigliamo di testarlo.</string>
<string name="notificationCloseActionExplanation">Se non specifichi alcun criterio, questa azione chiuderà TUTTE le notifiche. Quindi si consiglia di specificare almeno i criteri per almeno una applicazione, titolo o testo.</string>
<string name="profileWarning">Le impostazioni che modifichi in questa sezione possono far sì che tu non possa più notare certe cose dal tuo telefono. Possono perfino silenziare la sveglia. Quindi, qualunque cosa tu faccia, ti consigliamo di provarlo.</string>
<string name="ifString">se</string>
<string name="actionMediaControlNotice">Tieni presente che questa azione potrebbe non funzionare con TUTTI i lettori là fuori. E anche se lo facesse, non tutti i pulsanti funzionerebbero necessariamente.</string>
<string name="pleaseSelectActionValue">Si prega di selezionare un\'azione!</string>
<string name="stop">stop</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Controllo riproduzione multimediale</string>
<string name="next">prossimo</string>
<string name="previous">precedente</string>
<string name="pause">pausa</string>
<string name="play">riproduci</string>
<string name="playPause">attiva/disattiva riproduzione/pausa</string>
<string name="selectCommand">Seleziona comando</string>
<string name="actionMediaControl">Controllare la riproduzione multimediale</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">A causa della saggezza infinita di Google, l\'ultima versione di Android su cui questa funzione è nota per funzionare è %1 $s. Puoi configurarlo, ma probabilmente non avrà alcun effetto.</string>
<string name="screenState">Stato dello schermo</string>
<string name="selectDesiredState">Seleziona lo stato desiderato</string>
<string name="unlocked">Sbloccato</string>
<string name="off">spento</string>
<string name="on">attivo</string>
<string name="screenIs">lo schermo è %1$s</string>
<string name="sendEmailToDev">Invia email allo sviluppatore</string>
<string name="controlCenter">Centro di controllo</string>
<string name="emailContactNotice">L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.</string>
<string name="musicPlaying">La musica è in riproduzione</string>
<string name="musicIsPlaying">la musica è in riproduzione</string>
<string name="musicIsNotPlaying">la musica non viene riprodotta</string>
<string name="selectParameters">Selezionare i parametri</string>
<string name="musicCheckFrequencyTitle">Frequenza dei controlli [ms]</string>
<string name="musicCheckFrequencySummary">Millisecondi tra i controlli</string>
<string name="musicPlayingDetection">Rilevamento della riproduzione musicale</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 cerchio rotante non smette di girare, sai perché.</string>
<string name="lastProfile">Ultimo profilo:</string>
</resources>

View File

@ -667,4 +667,35 @@
<string name="comparisonCaseInsensitive">Vergelijkingen worden gedaan case-INsensitief</string>
<string name="profileWarning">De instellingen die je hier maakt kunnen ervoor zorgen dat je bepaalde dingen niet meer van je telefoon merkt. Ze kunnen zelfs je wekker dempen. Dus wat je ook doet - het wordt aanbevolen om het te testen.</string>
<string name="ifString">als</string>
<string name="emailContactNotice">E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.</string>
<string name="controlCenter">Controlecentrum</string>
<string name="sendEmailToDev">Stuur een e-mail naar de ontwikkelaar</string>
<string name="screenIs">scherm is %1$s</string>
<string name="on">op</string>
<string name="off">af</string>
<string name="unlocked">ontgrendeld</string>
<string name="selectDesiredState">Selecteer de gewenste status</string>
<string name="screenState">Schermstatus</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Vanwege de oneindige wijsheid van Google is de laatste Android-versie waarvan bekend is dat deze functie werkt% 1 $ s. U kunt het configureren, maar het zal waarschijnlijk geen effect hebben.</string>
<string name="actionMediaControl">Het afspelen van media regelen</string>
<string name="selectCommand">Opdracht Selecteren</string>
<string name="playPause">schakelaar afspelen/pauzeren</string>
<string name="play">afspelen</string>
<string name="pause">pauzeren</string>
<string name="previous">vorig</string>
<string name="next">volgend</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Het afspelen van media regelen</string>
<string name="stop">stoppen</string>
<string name="pleaseSelectActionValue">Selecteer een actie!</string>
<string name="actionMediaControlNotice">Houd er rekening mee dat deze actie mogelijk niet werkt met ALLE spelers die er zijn. En zelfs als dat zo is, werkt niet elke knop noodzakelijkerwijs.</string>
<string name="musicPlaying">Er wordt muziek afgespeeld</string>
<string name="selectParameters">Selecteer parameters</string>
<string name="musicIsPlaying">er wordt muziek afgespeeld</string>
<string name="musicIsNotPlaying">muziek wordt niet afgespeeld</string>
<string name="musicCheckFrequencyTitle">Controleer frequentie [ms]</string>
<string name="musicCheckFrequencySummary">Milliseconden tussen controles</string>
<string name="musicPlayingDetection">Detectie van het afspelen van muziek</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="lastProfile">Laatste profiel:</string>
</resources>

View File

@ -567,6 +567,7 @@
<string name="android.permission.ACCESS_NOTIFICATION_POLICY">Override do not disturb policy</string>
<string name="theseAreThePermissionsRequired">These are the permissions required:</string>
<string name="ruleXrequiresThis">Rule \"%1$s\" requires this.</string>
<string name="profileXrequiresThis">Profile \"%1$s\" requires this.</string>
<string name="helpTextActivityDetection">This feature can detect if you\'re currently on the go and if it is on foot or in which type of vehicle (to a certain extent). The feature is not fully built into Automation, but is provided by Google Play Services. Technically it does not give a yes/no result, but return a percentage to which level it is sure it detected you\'re status. You can setup the percentage value from which Automation will accept a result. Two remarks: 1) More than 1 status could occur at the same time. For example you might be WALKING inside a driving bus. 2) This sensor is relatively expensive in terms of battery usage. If it is possible you might consider using alternatives, e.g. require your car\'s handsfree device to be connected to detect you\'re driving.</string>
<string name="sendTextMessage">Send text message</string>
<string name="textToSend">Text to send</string>
@ -768,4 +769,31 @@
<string name="emailContactNotice">Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.</string>
<string name="controlCenter">Control center</string>
<string name="sendEmailToDev">Send email to developer</string>
<string name="screenIs">screen is %1$s</string>
<string name="on">on</string>
<string name="off">off</string>
<string name="unlocked">unlocked</string>
<string name="selectDesiredState">Select desired state</string>
<string name="screenState">Screen state</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Because of Google\'s infinite wisdom, the last Android version this feature is known to work on is %1$s. You can configure it, but it probably will not have any effect.</string>
<string name="actionMediaControl">Control media playback</string>
<string name="selectCommand">Select command</string>
<string name="playPause">toggle play/pause</string>
<string name="play">play</string>
<string name="pause">pause</string>
<string name="previous">previous</string>
<string name="next">next</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Control media playback</string>
<string name="stop">stop</string>
<string name="pleaseSelectActionValue">Please select an action!</string>
<string name="actionMediaControlNotice">Keep in mind that this action may not work with ALL players out there. And even if it does, not every buttons does necessarily work.</string>
<string name="musicPlaying">Music playing</string>
<string name="selectParameters">Select parameters</string>
<string name="musicIsPlaying">music is playing</string>
<string name="musicIsNotPlaying">music is not playing</string>
<string name="musicPlayingDetection">Music playing detection</string>
<string name="musicCheckFrequencyTitle">Check frequency [ms]</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="lastProfile">Last profile:</string>
</resources>

View File

@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.android.tools.build:gradle:7.1.1'
// NOTE: Do not place your application dependencies here; they belong
// 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

@ -1,3 +1,11 @@
* New trigger: screen state (on/off)
* New action: Create notification
* New action: Close notification(s)
* Fixed: Translation bug in dutch variables text
* New action: Control media playback
* Fixed: Translation bug in dutch variables text
* Fixed: Variables were not replaced when sending text messages
* Fixed: Service wouldn't always start after device has been powered on
* Fixed: Set ringtones on Android 11 and above
* 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,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,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,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

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip