Compare commits

..

53 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
06080bb456 Update 'app/src/main/java/com/jens/automation2/Actions.java' 2022-01-21 13:00:44 +01:00
a5fd23949d screen status trigger 2022-01-20 17:57:13 +01:00
59c7a2d313 Notification channels 2022-01-17 20:09:46 +01:00
ec61a3ffa5 Service notification hint 2022-01-16 20:24:12 +01:00
a0c4cb7b6f notification action 2022-01-15 23:36:42 +01:00
22899347a1 close notification action 2022-01-15 13:47:39 +01:00
4b84a0c2f5 close notification action 2022-01-15 01:41:00 +01:00
724192e80b close notification action 2022-01-14 19:57:32 +01:00
e6a7e2c5b5 ringmode bug fixed 2022-01-14 19:31:13 +01:00
e010e3392f ringmode bug fixed 2022-01-14 19:30:06 +01:00
f0853b3a30 close notification action 2022-01-11 17:27:07 +01:00
98185a79df close notification action 2022-01-11 16:04:04 +01:00
246a02371a notification action 2022-01-10 23:00:36 +01:00
9b8ae2271b Notification action 2022-01-10 19:57:55 +01:00
b2cd3cf17c Merge remote-tracking branch 'origin/notification_action' into development 2022-01-10 19:33:24 +01:00
cf4ec286ae Notification action 2022-01-10 19:32:44 +01:00
12f44aca8b notification action 2022-01-09 22:42:47 +01:00
87edd595ba notification trigger 2022-01-09 15:22:03 +01:00
75 changed files with 3671 additions and 1598 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 117
versionName "1.7.3"
versionCode 118
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,9 +53,14 @@ android {
targetSdkVersion 28
}
}
lint {
abortOnError false
checkReleaseBuilds false
}
}
dependencies {
implementation 'org.jetbrains:annotations:15.0'
googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:18.0.0'
@ -71,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": 117,
"versionName": "1.7.3-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"
@ -147,14 +154,17 @@
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityManageActionSendTextMessage" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageActionCloseNotification" />
<activity android:name=".ActivityManageTriggerProfile" />
<activity android:name=".ActivityManageTriggerTimeFrame" />
<activity android:name=".ActivityMaintenance" />
<activity android:name=".ActivityControlCenter" />
<activity android:name=".ActivityManageTriggerPhoneCall" />
<activity android:name=".ActivityManageActionBrightnessSetting" />
<activity android:name=".ActivityManageActionCreateNotification" />
<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,7 +22,6 @@ 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>();
@ -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,24 +472,21 @@ 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);
@ -530,12 +523,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -544,6 +531,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -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>();
@ -811,29 +641,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)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -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"
@ -145,14 +152,17 @@
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityManageActionSendTextMessage" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageActionCloseNotification" />
<activity android:name=".ActivityManageTriggerProfile" />
<activity android:name=".ActivityManageTriggerTimeFrame" />
<activity android:name=".ActivityMaintenance" />
<activity android:name=".ActivityControlCenter" />
<activity android:name=".ActivityManageTriggerPhoneCall" />
<activity android:name=".ActivityManageActionBrightnessSetting" />
<activity android:name=".ActivityManageActionCreateNotification" />
<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,7 +19,6 @@ 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>();
@ -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,24 +445,21 @@ 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);
@ -503,12 +496,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -517,6 +504,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -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>();
@ -784,29 +614,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)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -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"
@ -139,14 +140,17 @@
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityManageActionSendTextMessage" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageActionCloseNotification" />
<activity android:name=".ActivityManageTriggerProfile" />
<activity android:name=".ActivityManageTriggerTimeFrame" />
<activity android:name=".ActivityMaintenance" />
<activity android:name=".ActivityControlCenter" />
<activity android:name=".ActivityManageTriggerPhoneCall" />
<activity android:name=".ActivityManageActionBrightnessSetting" />
<activity android:name=".ActivityManageActionCreateNotification" />
<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,7 +22,6 @@ 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>();
@ -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,24 +472,21 @@ 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);
@ -530,12 +523,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -544,6 +531,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -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>();
@ -811,29 +641,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)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -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,9 +42,12 @@ public class Action
setDataConnection,
speakText,
playMusic,
controlMediaPlayback,
setScreenBrightness,
playSound,
vibrate,
createNotification,
closeNotification,
sendTextMessage;
public String getFullName(Context context)
@ -102,12 +106,18 @@ 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:
return context.getResources().getString(R.string.sendTextMessage);
case setScreenBrightness:
return context.getResources().getString(R.string.setScreenBrightness);
case createNotification:
return context.getResources().getString(R.string.createNotification);
case closeNotification:
return context.getResources().getString(R.string.closeNotifications);
default:
return "Unknown";
}
@ -154,7 +164,9 @@ public class Action
{
StringBuilder returnString = new StringBuilder();
switch(getAction())
try
{
switch (getAction())
{
case setWifi:
if (this.getParameter1())
@ -216,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;
@ -237,51 +252,106 @@ public class Action
case setScreenBrightness:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.setScreenBrightness));
break;
case createNotification:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.createNotification));
break;
case closeNotification:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.closeNotifications));
break;
default:
returnString.append(action.toString());
}
if(this.getAction().equals(Action_Enum.triggerUrl))
if (this.getAction().equals(Action_Enum.triggerUrl))
{
String[] components = parameter2.split(";");
if(components.length >= 3)
if (components.length >= 3)
{
returnString.append(": " + components[2]);
if(parameter1)
if (parameter1)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + ".");
}
else
returnString.append(": " + components[0]);
}
else if(this.getAction().equals(Action_Enum.startOtherActivity))
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))
else if (this.getAction().equals(Action_Enum.sendTextMessage))
{
String[] components = parameter2.split(Actions.smsSeparator);
if(components.length >= 2)
if (components.length >= 2)
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.toNumber) + " " + components[0]);
returnString.append(". " + Miscellaneous.getAnyContext().getResources().getString(R.string.message) + ": " + components[1]);
}
}
else if(this.getAction().equals(Action_Enum.setScreenBrightness))
else if (this.getAction().equals(Action_Enum.setScreenBrightness))
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.to) + " ");
if(parameter1)
if (parameter1)
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.brightnessAuto));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.brightnessManual));
returnString.append(" / " + Integer.parseInt(parameter2) + "%");
}
else if (this.getAction().equals(Action_Enum.closeNotification))
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.from) + " ");
String parts[] = this.getParameter2().split(Action.actionParameter2Split);
if (parts[0].equals(Trigger.anyAppString))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.anyApp));
else
if (parameter2 != null && parameter2.length() > 0)
returnString.append(": " + parameter2);
returnString.append(parts[0]);
if (!StringUtils.isBlank(parts[2]))
returnString.append(", " + Miscellaneous.getAnyContext().getResources().getString(R.string.ifString) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.title) + " " + Trigger.getMatchString(parts[1]) + " " + parts[2]);
if (parts.length > 4 && !StringUtils.isBlank(parts[4]))
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, "; "));
}
catch (Exception e)
{
returnString.append(": " + Miscellaneous.getAnyContext().getResources().getString(R.string.error));
}
return returnString.toString();
}
@ -439,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;
@ -451,6 +524,15 @@ public class Action
case playSound:
Actions.playSound(getParameter1(), getParameter2());
break;
case createNotification:
Actions.createNotification(this);
break;
case closeNotification:
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);
break;

View File

@ -8,13 +8,15 @@ import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
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;
@ -24,11 +26,13 @@ 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.WindowManager;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
@ -37,7 +41,9 @@ import com.jens.automation2.actions.wifi_router.MyOnStartTetheringCallback;
import com.jens.automation2.actions.wifi_router.MyOreoWifiManager;
import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.NotificationListener;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
@ -54,6 +60,7 @@ import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.KeyStore;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@ -64,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;
@ -79,6 +85,106 @@ public class Actions
public static final String wireguard_tunnel_down = "com.wireguard.android.action.SET_TUNNEL_DOWN";
public static final String wireguard_tunnel_refresh = "com.wireguard.android.action.REFRESH_TUNNEL_STATES";
public static void createNotification(Action action)
{
String[] elements = action.getParameter2().split(Action.actionParameter2Split);
Miscellaneous.logEvent("w", "createNotification", "Creating notification with title " + elements[0] + " and text " + elements[1], 3);
int notificationId = Math.round(Calendar.getInstance().getTimeInMillis()/1000);
try
{
String title = Miscellaneous.replaceVariablesInText(elements[0], Miscellaneous.getAnyContext());
String text = Miscellaneous.replaceVariablesInText(elements[1], Miscellaneous.getAnyContext());
Miscellaneous.createDismissibleNotification(title, text, notificationId, false, AutomationService.NOTIFICATION_CHANNEL_ID_RULES, null);
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "createNotification", "Error occurred while replacing vars: " + Log.getStackTraceString(e), 3);
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static void closeNotification(Action action)
{
NotificationManager nm = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
for(StatusBarNotification n : nm.getActiveNotifications())
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
String[] params = action.getParameter2().split(Action.actionParameter2Split);
String myApp = params[0];
String myTitleDir = params[1];
String requiredTitle = params[2];
String myTextDir = params[3];
String requiredText;
if (params.length >= 5)
requiredText = params[4];
else
requiredText = "";
for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications())
{
NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn);
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Checking if this notification should be closed in the context of rule " + action.getParentRule().getName() + ": "+ sn.toString(), 5);
if (!myApp.equals(Trigger.anyAppString))
{
if (!myApp.equalsIgnoreCase(sn.getApp()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification app name does not match rule.", 5);
continue;
}
}
else
{
/*
Notifications from Automation are disregarded to avoid infinite loops.
*/
if(myApp.equals(BuildConfig.APPLICATION_ID))
{
continue;
}
}
/*
If there are multiple notifications ("stacked") title or text might be null:
https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications
*/
// T I T L E
if (!StringUtils.isEmpty(requiredTitle))
{
if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification title does not match rule.", 5);
continue;
}
}
// T E X T
if (!StringUtils.isEmpty(requiredText))
{
if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification text does not match rule.", 5);
continue;
}
}
Miscellaneous.logEvent("i", "NotificationCloseCheck", "All criteria matches. Closing notification: " + sbn.getNotification().toString(), 3);
if(NotificationListener.getInstance() != null)
NotificationListener.getInstance().dismissNotification(sbn);
else
Miscellaneous.logEvent("i", "NotificationCloseCheck", "NotificationListener instance is null. Can\'t close notification.", 3);
}
}
}
}
public static class WifiStuff
{
public static Boolean setWifi(Context context, Boolean desiredState, boolean toggleActionIfPossible)
@ -120,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);
@ -930,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())
@ -1010,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();
}
}
@ -1074,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)
{
@ -1201,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);
@ -1315,7 +1421,7 @@ public class Actions
try
{
String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context);
autoMationServerRef.speak(textToSpeak, true);
automationServerRef.speak(textToSpeak, true);
}
catch (Exception e)
{
@ -1345,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)
{
@ -1377,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
@ -1490,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;
@ -1503,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;
@ -1516,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

@ -10,6 +10,7 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
@ -20,8 +21,9 @@ import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
public class ActivityMaintenance extends Activity
public class ActivityControlCenter extends Activity
{
final static int requestCodeImport = 1001;
final static int requestCodeExport = 1002;
@ -30,13 +32,14 @@ public class ActivityMaintenance extends Activity
final static String prefsFileName = "com.jens.automation2_preferences.xml";
TextView tvFileStoreLocation, tvAppVersion;
Button bVolumeTest, bMoreSettings, bSettingsSetToDefault, bShareConfigAndLog, bImportConfiguration, bExportConfiguration;
Button bVolumeTest, bMoreSettings, bSettingsSetToDefault, bSendEmailToDev, bImportConfiguration, bExportConfiguration;
CheckBox chkShareConfigAndLog;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintenance);
setContentView(R.layout.activity_control_center);
bVolumeTest = (Button) findViewById(R.id.bVolumeTest);
bVolumeTest.setOnClickListener(new View.OnClickListener()
@ -44,18 +47,25 @@ public class ActivityMaintenance extends Activity
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMaintenance.this, ActivityVolumeTest.class);
Intent intent = new Intent(ActivityControlCenter.this, ActivityVolumeTest.class);
startActivity(intent);
}
});
bShareConfigAndLog = (Button) findViewById(R.id.bShareConfigAndLog);
bShareConfigAndLog.setOnClickListener(new View.OnClickListener()
chkShareConfigAndLog = (CheckBox)findViewById(R.id.chkShareConfigAndLog);
bSendEmailToDev = (Button) findViewById(R.id.bSendEmailToDev);
bSendEmailToDev.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
getShareConfigAndLogDialogue(ActivityMaintenance.this).show();
if(chkShareConfigAndLog.isChecked())
getShareConfigAndLogDialogue(ActivityControlCenter.this).show();
else
{
String subject = "Automation";
Miscellaneous.sendEmail(ActivityControlCenter.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), null);
}
}
});
@ -65,17 +75,17 @@ public class ActivityMaintenance extends Activity
@Override
public void onClick(View v)
{
getDefaultSettingsDialog(ActivityMaintenance.this).show();
getDefaultSettingsDialog(ActivityControlCenter.this).show();
}
});
Button bMoreSettings = (Button) findViewById(R.id.bMoreSettings);
bMoreSettings = (Button) findViewById(R.id.bMoreSettings);
bMoreSettings.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(ActivityMaintenance.this, ActivitySettings.class);
Intent myIntent = new Intent(ActivityControlCenter.this, ActivitySettings.class);
startActivityForResult(myIntent, requestCodeMoreSettings);
}
});
@ -123,7 +133,7 @@ public class ActivityMaintenance extends Activity
if (AutomationService.isMyServiceRunning(this))
AutomationService.getInstance().serviceInterface(AutomationService.serviceCommands.reloadSettings);
if (AutomationService.isMyServiceRunning(ActivityMaintenance.this))
if (AutomationService.isMyServiceRunning(ActivityControlCenter.this))
Toast.makeText(this, getResources().getString(R.string.settingsWillTakeTime), Toast.LENGTH_LONG).show();
break;
@ -170,7 +180,7 @@ public class ActivityMaintenance extends Activity
if (Miscellaneous.copyDocumentFileToFile(file, dstRules))
filesImported++;
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.rulesImportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.rulesImportError), Toast.LENGTH_LONG).show();
}
}
else if (file.getName().equals(prefsFileName))
@ -183,7 +193,7 @@ public class ActivityMaintenance extends Activity
if (Miscellaneous.copyDocumentFileToFile(file, dstPrefs))
filesImported++;
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.prefsImportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.prefsImportError), Toast.LENGTH_LONG).show();
}
}
}
@ -191,12 +201,12 @@ public class ActivityMaintenance extends Activity
if(applicableFilesFound > 0)
{
if(filesImported == 0)
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
else if(filesImported < applicableFilesFound)
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.notAllFilesImported), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.notAllFilesImported), Toast.LENGTH_LONG).show();
else if (filesImported == applicableFilesFound)
{
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.configurationImportedSuccessfully), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.configurationImportedSuccessfully), Toast.LENGTH_LONG).show();
try
{
@ -208,19 +218,19 @@ public class ActivityMaintenance extends Activity
catch (Exception e)
{
Miscellaneous.logEvent("e", "Reading import", "Rules re-read failed: " + Log.getStackTraceString(e), 1);
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.errorReadingPoisAndRulesFromFile), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.errorReadingPoisAndRulesFromFile), Toast.LENGTH_LONG).show();
}
Settings.readFromPersistentStorage(ActivityMaintenance.this);
Settings.readFromPersistentStorage(ActivityControlCenter.this);
}
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
}
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noApplicableFilesFoundInDirectory), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noApplicableFilesFoundInDirectory), Toast.LENGTH_LONG).show();
}
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noApplicableFilesFoundInDirectory), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noApplicableFilesFoundInDirectory), Toast.LENGTH_LONG).show();
}
void exportFiles(Uri uriTree)
@ -252,12 +262,12 @@ public class ActivityMaintenance extends Activity
if(dstRules.canWrite() && dstPrefs.canWrite())
{
if(Miscellaneous.copyFileToDocumentFile(srcRules, dstRules) && Miscellaneous.copyFileToDocumentFile(srcPrefs, dstPrefs))
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.configurationExportedSuccessfully), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.configurationExportedSuccessfully), Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.ConfigurationExportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.ConfigurationExportError), Toast.LENGTH_LONG).show();
}
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.ConfigurationExportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.ConfigurationExportError), Toast.LENGTH_LONG).show();
}
private static AlertDialog getDefaultSettingsDialog(final Context context)
@ -296,16 +306,16 @@ public class ActivityMaintenance extends Activity
srcFilesList.add(Miscellaneous.getWriteableFolder() + "/../shared_prefs/" + prefsFileName);
String logFilePath = Miscellaneous.getWriteableFolder() + "/" + Miscellaneous.logFileName;
if((new File(logFilePath)).exists())
if ((new File(logFilePath)).exists())
srcFilesList.add(logFilePath);
String logFilePathArchive = Miscellaneous.getWriteableFolder() + "/" + Miscellaneous.logFileName + "-old";
if((new File(logFilePathArchive)).exists())
if ((new File(logFilePathArchive)).exists())
srcFilesList.add(logFilePathArchive);
String[] srcFiles = srcFilesList.toArray(new String[srcFilesList.size()]);
if(dstZipFile.exists())
if (dstZipFile.exists())
dstZipFile.delete();
Miscellaneous.zip(srcFiles, dstZipFile.getAbsolutePath());
@ -319,9 +329,10 @@ public class ActivityMaintenance extends Activity
Uri uri = Uri.parse("content://com.jens.automation2/" + Settings.zipFileName);
Miscellaneous.sendEmail(ActivityMaintenance.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), uri);
Miscellaneous.sendEmail(ActivityControlCenter.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), uri);
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
@ -337,7 +348,24 @@ public class ActivityMaintenance 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();
}
@ -367,7 +395,7 @@ public class ActivityMaintenance extends Activity
{
// if you reach this place, it means there is no any file
// explorer app installed on your device
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noFileManageInstalled), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFileManageInstalled), Toast.LENGTH_LONG).show();
}
}

View File

@ -135,7 +135,7 @@ public class ActivityMainRules extends ActivityGeneric
else
holder = (RuleHolder) v.getTag();
System.out.println("Position ["+position+"]");
// System.out.println("Position ["+position+"]");
Rule r = Rule.getRuleCollection().get(position);
holder.tvRuleName.setText(r.getName());
if(r.isRuleActive())
@ -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

@ -3,7 +3,6 @@ package com.jens.automation2;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -11,7 +10,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@ -29,29 +27,25 @@ import androidx.core.text.HtmlCompat;
import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.CellLocationChangedReceiver;
import com.jens.automation2.location.LocationProvider;
import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Calendar;
@SuppressLint("NewApi")
public class ActivityMainScreen extends ActivityGeneric
{
private static boolean guiChangeInProgress = false;
static boolean guiChangeInProgress = false;
static ActivityMainScreen activityMainScreenInstance = null;
static boolean updateNoteDisplayed = false;
static boolean uiUpdateRunning = false;
private static ActivityMainScreen activityMainScreenInstance = null;
private ToggleButton toggleService, tbLockSound;
private Button bShowHelp, bPrivacy, bSettingsErase, bAddSoundLockTIme, bDonate;
private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvlockSoundDuration;
private static boolean updateNoteDisplayed = false;
ToggleButton toggleService, tbLockSound;
Button bShowHelp, bPrivacy, bAddSoundLockTIme, bDonate, bControlCenter;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration;
private ListView lvRuleHistory;
private ArrayAdapter<Rule> ruleHistoryListViewAdapter;
private static boolean uiUpdateRunning = false;
ListView lvRuleHistory;
ArrayAdapter<Rule> ruleHistoryListViewAdapter;
@Override
public void onCreate(Bundle savedInstanceState)
@ -74,12 +68,13 @@ 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);
tvMainScreenNoteNews = (TextView) findViewById(R.id.tvMainScreenNoteNews);
tvlockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tvLockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
@ -99,7 +94,8 @@ public class ActivityMainScreen extends ActivityGeneric
if (toggleService.isChecked())
{
startAutomationService(getBaseContext(), false);
} else
}
else
{
stopAutomationService();
}
@ -147,13 +143,13 @@ public class ActivityMainScreen extends ActivityGeneric
}
});
Button bSettings = (Button) findViewById(R.id.bSettings);
bSettings.setOnClickListener(new OnClickListener()
bControlCenter = (Button) findViewById(R.id.bControlCenter);
bControlCenter.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(ActivityMainScreen.this, ActivityMaintenance.class);
Intent myIntent = new Intent(ActivityMainScreen.this, ActivityControlCenter.class);
startActivity(myIntent);
}
});
@ -370,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
{
@ -378,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;
@ -395,21 +402,21 @@ public class ActivityMainScreen extends ActivityGeneric
long millis = end.getTimeInMillis() - now.getTimeInMillis();
long minutes = millis/1000/60;
if(minutes < 60)
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(minutes + " min..."));
activityMainScreenInstance.tvLockSoundDuration.setText(String.valueOf(minutes + " min..."));
else
{
double hours = (double)minutes / 60.0;
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(Math.round(hours * 100.0) / 100.0) + " h...");
activityMainScreenInstance.tvLockSoundDuration.setText(String.valueOf(Math.round(hours * 100.0) / 100.0) + " h...");
}
}
else
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(""));
activityMainScreenInstance.tvLockSoundDuration.setText(String.valueOf(""));
}
else
{
activityMainScreenInstance.tbLockSound.setChecked(false);
activityMainScreenInstance.tbLockSound.setEnabled(false);
activityMainScreenInstance.tvlockSoundDuration.setText("");
activityMainScreenInstance.tvLockSoundDuration.setText("");
}
Settings.writeSettings(activityMainScreenInstance);
// uiUpdateRunning = false;

View File

@ -10,10 +10,13 @@ import android.widget.CompoundButton;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import org.jetbrains.annotations.Nullable;
public class ActivityManageActionBrightnessSetting extends Activity
{
public static final String intentNameAutoBrightness = "autoBrightness";
public static final String intentNameBrightnessValue = "brightnessValue";
CheckBox chkAutoBrightness;
SeekBar sbBrightness;
Button bApplyBrightness;
@ -22,7 +25,7 @@ public class ActivityManageActionBrightnessSetting extends Activity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
setContentView(R.layout.activity_manage_brightness_setting);
setContentView(R.layout.activity_manage_action_brightness_settings);
super.onCreate(savedInstanceState);
chkAutoBrightness = (CheckBox)findViewById(R.id.chkAutoBrightness);
@ -32,11 +35,11 @@ public class ActivityManageActionBrightnessSetting extends Activity
Intent input = getIntent();
if(input.hasExtra("autoBrightness"))
chkAutoBrightness.setChecked(input.getBooleanExtra("autoBrightness", false));
if(input.hasExtra(intentNameAutoBrightness))
chkAutoBrightness.setChecked(input.getBooleanExtra(intentNameAutoBrightness, false));
if(input.hasExtra("brightnessValue"))
sbBrightness.setProgress(input.getIntExtra("brightnessValue", 0));
if(input.hasExtra(intentNameBrightnessValue))
sbBrightness.setProgress(input.getIntExtra(intentNameBrightnessValue, 0));
bApplyBrightness.setOnClickListener(new View.OnClickListener()
{
@ -44,8 +47,8 @@ public class ActivityManageActionBrightnessSetting extends Activity
public void onClick(View view)
{
Intent answer = new Intent();
answer.putExtra("autoBrightness", chkAutoBrightness.isChecked());
answer.putExtra("brightnessValue", sbBrightness.getProgress());
answer.putExtra(intentNameAutoBrightness, chkAutoBrightness.isChecked());
answer.putExtra(intentNameBrightnessValue, sbBrightness.getProgress());
setResult(RESULT_OK, answer);
finish();
}

View File

@ -0,0 +1,397 @@
package com.jens.automation2;
import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ActivityManageActionCloseNotification extends Activity
{
public static final String intentNameNotificationApp = "app";
public static final String intentNameNotificationTitleDir = "titleDir";
public static final String intentNameNotificationTitle = "title";
public static final String intentNameNotificationTextDir = "textDir";
public static final String intentNameNotificationText = "text";
public static final String intentNameNotificationDirection = "direction";
boolean edit = false;
ProgressDialog progressDialog = null;
EditText etNotificationTitle, etNotificationText;
Button bSelectApp, bSaveActionCloseNotification;
Spinner spinnerTitleDirection, spinnerTextDirection;
TextView tvSelectedApplication;
private static List<PackageInfo> pInfos = null;
public static Trigger resultingTrigger;
private static String[] directions;
ArrayAdapter<String> directionSpinnerAdapter;
public static void getActivityList(final Context context)
{
if(pInfos == null)
{
pInfos = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
Collections.sort(pInfos, new Comparator<PackageInfo>()
{
public int compare(PackageInfo obj1, PackageInfo obj2)
{
String name1 = "";
String name2 = "";
ApplicationInfo aInfo1 = obj1.applicationInfo;
if (aInfo1 != null)
{
name1 = (String) context.getPackageManager().getApplicationLabel(aInfo1);
}
ApplicationInfo aInfo2 = obj2.applicationInfo;
if (aInfo2 != null)
{
name2 = (String) context.getPackageManager().getApplicationLabel(aInfo2);
}
return name1.compareTo(name2);
}
});
}
}
public static String[] getApplicationNameListString(Context myContext)
{
// Generate the actual list
getActivityList(myContext);
ArrayList<String> returnList = new ArrayList<String>();
for (PackageInfo pInfo : pInfos)
{
ApplicationInfo aInfo = pInfo.applicationInfo;
if (aInfo != null)
{
String aLabel;
aLabel = (String) myContext.getPackageManager().getApplicationLabel(aInfo);
ActivityInfo[] aInfos = pInfo.activities;
if (aInfos != null && aInfos.length > 0) // Only put Applications into the list that have packages.
{
if(!returnList.contains(aLabel))
returnList.add(aLabel);
}
}
}
return returnList.toArray(new String[returnList.size()]);
}
public static String[] getPackageListString(Context myContext, String applicationLabel)
{
// Generate the actual list
getActivityList(myContext);
ArrayList<String> returnList = new ArrayList<String>();
for (PackageInfo pInfo : pInfos)
{
if(myContext.getPackageManager().getApplicationLabel(pInfo.applicationInfo).equals(applicationLabel))
{
ActivityInfo[] aInfos = pInfo.activities;
if (aInfos != null && aInfos.length > 0)
{
returnList.add(pInfo.packageName);
}
}
}
return returnList.toArray(new String[returnList.size()]);
}
public static String[] getPackageListString(Context myContext)
{
// Generate the actual list
getActivityList(myContext);
ArrayList<String> returnList = new ArrayList<String>();
for (PackageInfo pInfo : pInfos)
{
ActivityInfo[] aInfos = pInfo.activities;
if (aInfos != null && aInfos.length > 0)
{
returnList.add(pInfo.packageName);
}
else
Miscellaneous.logEvent("w", "Empty Application", "Application " + myContext.getPackageManager().getApplicationLabel(pInfo.applicationInfo) + " doesn\'t have packages.", 5);
}
return returnList.toArray(new String[returnList.size()]);
}
public static String[] getActivityListForPackageName(String packageName)
{
ArrayList<String> returnList = new ArrayList<String>();
for (PackageInfo pInfo : pInfos)
{
if(pInfo.packageName.equals(packageName))
{
ActivityInfo[] aInfos = pInfo.activities;
if (aInfos != null)
{
for (ActivityInfo activityInfo : aInfos)
{
returnList.add(activityInfo.name);
}
}
}
}
return returnList.toArray(new String[returnList.size()]);
}
public static ActivityInfo getActivityInfoForPackageNameAndActivityName(String packageName, String activityName)
{
for (PackageInfo pInfo : pInfos)
{
if(pInfo.packageName.equals(packageName))
{
ActivityInfo[] aInfos = pInfo.activities;
if (aInfos != null)
{
for (ActivityInfo activityInfo : aInfos)
{
if(activityInfo.name.equals(activityName))
return activityInfo;
}
}
}
}
return null;
}
private AlertDialog getActionStartActivityDialog1()
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectApplication));
final String[] applicationArray = ActivityManageActionCloseNotification.getApplicationNameListString(this);
alertDialogBuilder.setItems(applicationArray, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
getActionStartActivityDialog2(applicationArray[which]).show();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private AlertDialog getActionStartActivityDialog2(String applicationName)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectPackageOfApplication));
final String[] packageArray = ActivityManageActionCloseNotification.getPackageListString(this, applicationName);
alertDialogBuilder.setItems(packageArray, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//getActionStartActivityDialog3(packageArray[which]).show();
//Miscellaneous.messageBox(getResources().getString(R.string.hint), getResources().getString(R.string.chooseActivityHint), ActivityManageNotificationTrigger.this).show();
tvSelectedApplication.setText(packageArray[which]);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private AlertDialog getActionStartActivityDialog3(final String packageName)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectActivityToBeStarted));
final String activityArray[] = ActivityManageActionCloseNotification.getActivityListForPackageName(packageName);
alertDialogBuilder.setItems(activityArray, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
ActivityInfo ai = ActivityManageActionCloseNotification.getActivityInfoForPackageNameAndActivityName(packageName, activityArray[which]);
tvSelectedApplication.setText(ai.packageName + ";" + ai.name);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_close_notification);
etNotificationTitle = (EditText)findViewById(R.id.etNotificationTitle);
etNotificationText = (EditText)findViewById(R.id.etNotificationText);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bSaveActionCloseNotification = (Button)findViewById(R.id.bSaveActionCloseNotification);
spinnerTitleDirection = (Spinner)findViewById(R.id.spinnerTitleDirection);
spinnerTextDirection = (Spinner)findViewById(R.id.spinnerTextDirection);
tvSelectedApplication = (TextView)findViewById(R.id.etActivityOrActionPath);
directions = new String[] {
getResources().getString(R.string.directionStringEquals),
getResources().getString(R.string.directionStringContains),
getResources().getString(R.string.directionStringStartsWith),
getResources().getString(R.string.directionStringEndsWith),
getResources().getString(R.string.directionStringNotEquals)
};
directionSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionCloseNotification.directions);
spinnerTitleDirection.setAdapter(directionSpinnerAdapter);
spinnerTextDirection.setAdapter(directionSpinnerAdapter);
directionSpinnerAdapter.notifyDataSetChanged();
bSelectApp.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionCloseNotification.this, "", ActivityManageActionCloseNotification.this.getResources().getString(R.string.gettingListOfInstalledApplications));
}
});
bSaveActionCloseNotification.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
String app;
if(tvSelectedApplication.getText().toString().equalsIgnoreCase(getResources().getString(R.string.anyApp)))
app = Trigger.anyAppString;
else
app = tvSelectedApplication.getText().toString();
String titleDir = Trigger.getMatchCode(spinnerTitleDirection.getSelectedItem().toString());
String title = etNotificationTitle.getText().toString();
String textDir = Trigger.getMatchCode(spinnerTextDirection.getSelectedItem().toString());
String text = etNotificationText.getText().toString();
Intent responseData = new Intent();
if(edit)
{
// editedNotificationAction.setTriggerParameter(chkNotificationDirection.isChecked());
responseData.putExtra(ActivityManageRule.intentNameActionParameter2, app + Action.actionParameter2Split + titleDir + Action.actionParameter2Split + title + Action.actionParameter2Split + textDir + Action.actionParameter2Split + text);
ActivityManageActionCloseNotification.this.setResult(RESULT_OK, responseData);
}
else
{
// data.putExtra(intentNameNotificationDirection, chkNotificationDirection.isChecked());
responseData.putExtra(ActivityManageRule.intentNameActionParameter2,
app + Action.actionParameter2Split +
titleDir + Action.actionParameter2Split +
title + Action.actionParameter2Split +
textDir + Action.actionParameter2Split +
text
);
// data.putExtra(intentNameNotificationApp, app);
// data.putExtra(intentNameNotificationTitleDir, titleDir);
// data.putExtra(intentNameNotificationTitle, title);
// data.putExtra(intentNameNotificationTextDir, textDir);
// data.putExtra(intentNameNotificationText, text);
ActivityManageActionCloseNotification.this.setResult(RESULT_OK, responseData);
}
finish();
}
});
Intent i = getIntent();
if(!StringUtils.isBlank(i.getStringExtra(ActivityManageRule.intentNameActionParameter2)))
{
edit = true;
loadValuesIntoGui(i.getStringExtra(ActivityManageRule.intentNameActionParameter2));
}
}
private void loadValuesIntoGui(String param)
{
String[] params = param.split(Action.actionParameter2Split);
String app = params[0];
String titleDir = params[1];
String title = params[2];
String textDir = params[3];
String text;
if (params.length >= 5)
text = params[4];
else
text = "";
if(!app.equals(Trigger.anyAppString))
tvSelectedApplication.setText(app);
for(int i = 0; i < directions.length; i++)
{
if(Trigger.getMatchCode(directions[i]).equalsIgnoreCase(titleDir))
spinnerTitleDirection.setSelection(i);
if(Trigger.getMatchCode(directions[i]).equalsIgnoreCase(textDir))
spinnerTextDirection.setSelection(i);
}
if(title.length() > 0)
etNotificationTitle.setText(title);
if(text.length() > 0)
etNotificationText.setText(text);
}
private class GetActivityListTask extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params)
{
getActivityList(ActivityManageActionCloseNotification.this);
return null;
}
@Override
protected void onPostExecute(Void result)
{
progressDialog.dismiss();
getActionStartActivityDialog1().show();
}
}
}

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

@ -0,0 +1,66 @@
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.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
public class ActivityManageActionCreateNotification extends Activity
{
public static final String intentNameNotificationTitle = "notificationTitle";
public static final String intentNameNotificationText = "notificationText";
EditText etNotificationTitle, etNotificationText;
Button bSaveActionNotification;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_create_notification);
etNotificationTitle = (EditText) findViewById(R.id.etNotificationTitle);
etNotificationText = (EditText)findViewById(R.id.etNotificationText);
bSaveActionNotification = (Button)findViewById(R.id.bSaveActionNotification);
Intent input = getIntent();
if(input.hasExtra(intentNameNotificationTitle))
etNotificationTitle.setText(input.getStringExtra(intentNameNotificationTitle));
if(input.hasExtra(intentNameNotificationText))
etNotificationText.setText(input.getStringExtra(intentNameNotificationText));
bSaveActionNotification.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
if(StringUtils.isBlank(etNotificationTitle.getText().toString()))
{
Toast.makeText(ActivityManageActionCreateNotification.this, getResources().getString(R.string.enterTitle), Toast.LENGTH_LONG).show();
return;
}
if(StringUtils.isBlank(etNotificationText.getText().toString()))
{
Toast.makeText(ActivityManageActionCreateNotification.this, getResources().getString(R.string.enterText), Toast.LENGTH_LONG).show();
return;
}
Intent answer = new Intent();
answer.putExtra(intentNameNotificationTitle, etNotificationTitle.getText().toString());
answer.putExtra(intentNameNotificationText, etNotificationText.getText().toString());
setResult(RESULT_OK, answer);
finish();
}
});
}
}

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;
@ -55,6 +59,8 @@ public class ActivityManageActionStartActivity extends Activity
final static String startByActivityString = "0";
final static String startByBroadcastString = "1";
final static int requestCodeForRequestQueryAllPackagesPermission = 4711;
private class CustomPackageInfo extends PackageInfo implements Comparable<CustomPackageInfo>
{
@Override
@ -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;
@ -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 critGps = new Criteria();
critGps.setAltitudeRequired(false);
critGps.setSpeedRequired(false);
critGps.setBearingRequired(false);
critGps.setCostAllowed(true);
critGps.setAccuracy(Criteria.ACCURACY_FINE);
Criteria criteriaGps = new Criteria();
criteriaGps.setAltitudeRequired(false);
criteriaGps.setSpeedRequired(false);
criteriaGps.setBearingRequired(false);
criteriaGps.setCostAllowed(true);
criteriaGps.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,6 +314,20 @@ public class ActivityManagePoi extends Activity
public void onClick(DialogInterface dialog, int which)
{
progressDialog = ProgressDialog.show(ActivityManagePoi.this, "", getResources().getString(R.string.gettingPosition), true, true);
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();
}
};

View File

@ -45,6 +45,8 @@ public class ActivityManageProfile extends Activity
TextView tvIncomingCallsRingtone, tvNotificationsRingtone;
EditText etName;
boolean guiUpdate = false;
File incomingCallsRingtone = null, notificationsRingtone = null;
ArrayAdapter<String> soundModeAdapter;
@ -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;
@ -102,7 +99,7 @@ public class ActivityManageRule extends Activity
final static int requestCodeTriggerDeviceOrientationAdd = 301;
final static int requestCodeTriggerDeviceOrientationEdit = 302;
final static int requestCodeTriggerNotificationAdd = 8000;
final static int requestCodeTriggerNfcNotificationEdit = 8001;
final static int requestCodeTriggerNotificationEdit = 8001;
final static int requestCodeActionPlaySoundAdd = 501;
final static int requestCodeActionPlaySoundEdit = 502;
final static int requestCodeTriggerPhoneCallAdd = 601;
@ -115,6 +112,12 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionSendTextMessageEdit = 5002;
final static int requestCodeActionVibrateAdd = 801;
final static int requestCodeActionVibrateEdit = 802;
final static int requestCodeActionCreateNotificationAdd = 803;
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()
{
@ -266,7 +269,7 @@ public class ActivityManageRule extends Activity
ActivityManageTriggerNotification.editedNotificationTrigger = selectedTrigger;
Intent notificationEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerNotification.class);
notificationEditor.putExtra("edit", true);
startActivityForResult(notificationEditor, requestCodeTriggerNfcNotificationEdit);
startActivityForResult(notificationEditor, requestCodeTriggerNotificationEdit);
break;
case phoneCall:
ActivityManageTriggerPhoneCall.editedPhoneCallTrigger = selectedTrigger;
@ -353,8 +356,8 @@ public class ActivityManageRule extends Activity
break;
case setScreenBrightness:
Intent activityEditScreenBrightnessIntent = new Intent(ActivityManageRule.this, ActivityManageActionBrightnessSetting.class);
activityEditScreenBrightnessIntent.putExtra("autoBrightness", a.getParameter1());
activityEditScreenBrightnessIntent.putExtra("brightnessValue", Integer.parseInt(a.getParameter2()));
activityEditScreenBrightnessIntent.putExtra(ActivityManageActionBrightnessSetting.intentNameAutoBrightness, a.getParameter1());
activityEditScreenBrightnessIntent.putExtra(ActivityManageActionBrightnessSetting.intentNameBrightnessValue, Integer.parseInt(a.getParameter2()));
startActivityForResult(activityEditScreenBrightnessIntent, requestCodeActionScreenBrightnessEdit);
break;
case vibrate:
@ -362,6 +365,23 @@ 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);
activityEditCreateNotificationIntent.putExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle, elements[0]);
activityEditCreateNotificationIntent.putExtra(ActivityManageActionCreateNotification.intentNameNotificationText, elements[1]);
startActivityForResult(activityEditCreateNotificationIntent, requestCodeActionCreateNotificationEdit);
break;
case closeNotification:
Intent activityEditCloseNotificationIntent = new Intent(ActivityManageRule.this, ActivityManageActionCloseNotification.class);
activityEditCloseNotificationIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditCloseNotificationIntent, requestCodeActionCloseNotificationEdit);
break;
case playSound:
Intent actionPlaySoundIntent = new Intent(context, ActivityManageActionPlaySound.class);
actionPlaySoundIntent.putExtra("edit", true);
@ -464,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()))
@ -489,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));
}
@ -507,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));
}
@ -567,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)};
@ -588,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);
@ -668,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)};
@ -678,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();
}
});
@ -687,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
@ -999,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()
{
@ -1088,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;
}
@ -1127,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();
}
@ -1260,7 +1318,7 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerNfcNotificationEdit)
else if(requestCode == requestCodeTriggerNotificationEdit)
{
if(resultCode == RESULT_OK)
{
@ -1335,8 +1393,8 @@ public class ActivityManageRule extends Activity
{
if(resultCode == RESULT_OK)
{
newAction.setParameter1(data.getBooleanExtra("autoBrightness", false));
newAction.setParameter2(String.valueOf(data.getIntExtra("brightnessValue", 0)));
newAction.setParameter1(data.getBooleanExtra(ActivityManageActionBrightnessSetting.intentNameAutoBrightness, false));
newAction.setParameter2(String.valueOf(data.getIntExtra(ActivityManageActionBrightnessSetting.intentNameBrightnessValue, 0)));
newAction.setParentRule(ruleToEdit);
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
@ -1367,6 +1425,40 @@ 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)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle)
+ Action.actionParameter2Split +
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationText)
);
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCloseNotificationAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionVibrateEdit)
{
if(resultCode == RESULT_OK)
@ -1379,6 +1471,46 @@ 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)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle))
ruleToEdit.getActionSet().get(editIndex).setParameter2(
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle)
+ Action.actionParameter2Split +
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationText)
);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCloseNotificationEdit)
{
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 == requestCodeActionPlaySoundAdd)
{
if(resultCode == RESULT_OK)
@ -1513,12 +1645,18 @@ 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()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Action_Enum.vibrate.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.vibrate));
else if(types[i].toString().equals(Action_Enum.createNotification.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Action_Enum.closeNotification.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Action_Enum.sendTextMessage.toString()))
{
// if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageSpecificRule.this, "android.permission.SEND_SMS") && !Miscellaneous.isGooglePlayInstalled(ActivityManageSpecificRule.this))
@ -1681,6 +1819,24 @@ 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);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCreateNotification.class);
startActivityForResult(intent, requestCodeActionCreateNotificationAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.closeNotification.toString()))
{
newAction.setAction(Action_Enum.closeNotification);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCloseNotification.class);
startActivityForResult(intent, requestCodeActionCloseNotificationAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setScreenBrightness.toString()))
{
newAction.setAction(Action_Enum.setScreenBrightness);

View File

@ -263,7 +263,7 @@ public class ActivityManageTriggerNotification extends Activity
etNotificationTitle = (EditText)findViewById(R.id.etNotificationTitle);
etNotificationText = (EditText)findViewById(R.id.etNotificationText);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bSaveTriggerNotification = (Button)findViewById(R.id.bSaveTriggerNotification);
bSaveTriggerNotification = (Button)findViewById(R.id.bSaveActionCloseNotification);
spinnerTitleDirection = (Spinner)findViewById(R.id.spinnerTitleDirection);
spinnerTextDirection = (Spinner)findViewById(R.id.spinnerTextDirection);
tvSelectedApplication = (TextView)findViewById(R.id.etActivityOrActionPath);
@ -312,7 +312,7 @@ public class ActivityManageTriggerNotification extends Activity
{
String app;
if(tvSelectedApplication.getText().toString().equalsIgnoreCase(getResources().getString(R.string.anyApp)))
app = "-1";
app = Trigger.anyAppString;
else
app = tvSelectedApplication.getText().toString();
@ -367,7 +367,7 @@ public class ActivityManageTriggerNotification extends Activity
else
text = "";
if(!app.equals("-1"))
if(!app.equals(Trigger.anyAppString))
tvSelectedApplication.setText(app);
for(int i = 0; i < directions.length; i++)

View File

@ -66,14 +66,21 @@ public class ActivityManageTriggerProfile extends Activity
String profileName = values[0];
List<Profile> profileList = Profile.getProfileCollection();
boolean found = false;
for(int i = 0; i < profileList.size(); i++)
{
if(profileList.get(i).getName().equals(profileName))
{
spinnerProfiles.setSelection(i);
found = true;
break;
}
}
if(!found)
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.profileWasNotFound), ActivityManageTriggerProfile.this).show();
}
}
catch(Exception e)

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,9 +379,9 @@ 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
@ -382,6 +389,7 @@ public class ActivityPermissions extends Activity
}
}
}
}
/*
Not all permissions need to be asked for.
@ -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,9 +538,13 @@ 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);
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case setAirplaneMode:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@ -588,7 +603,7 @@ public class ActivityPermissions extends Activity
// addToArrayListUnique("android.permission.TETHER_PRIVILEGED", requiredPermissions);
break;
case speakText:
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case startOtherActivity:
if(
@ -608,7 +623,7 @@ public class ActivityPermissions extends Activity
break;
case triggerUrl:
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case turnBluetoothOff:
addToArrayListUnique(Manifest.permission.BLUETOOTH_ADMIN, requiredPermissions);
@ -649,6 +664,9 @@ public class ActivityPermissions extends Activity
case playSound:
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case closeNotification:
addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions);
break;
case turnScreenOnOrOff:
if(action.getParameter1())
addToArrayListUnique(Manifest.permission.WAKE_LOCK, requiredPermissions);
@ -852,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))
@ -1150,7 +1194,7 @@ public class ActivityPermissions extends Activity
}
}
static ArrayList<String> checkPermissionsInVariableUse(String text, ArrayList<String> permsList)
static ArrayList<String> getPermissionsForVariablesInUse(String text, ArrayList<String> permsList)
{
/*
[uniqueid]

View File

@ -41,8 +41,14 @@ public class AutomationService extends Service implements OnInitListener
protected final static int notificationIdRestrictions = 1005;
protected final static int notificationIdLocationRestriction = 1006;
final static String NOTIFICATION_CHANNEL_ID = "com.jens.automation2";
final static String channelName = "Service notification";
final static String NOTIFICATION_CHANNEL_ID_SERVICE = "com.jens.automation2_service";
final static String NOTIFICATION_CHANNEL_NAME_SERVICE = "Service notification";
final static String NOTIFICATION_CHANNEL_ID_FUNCTIONALITY = "com.jens.automation2_functionality";
final static String NOTIFICATION_CHANNEL_NAME_FUNCTIONALITY = "Functionality information";
final static String NOTIFICATION_CHANNEL_ID_RULES = "com.jens.automation2_rules";
final static String NOTIFICATION_CHANNEL_NAME_RULES = "Rule notifications";
protected static Notification myNotification;
protected static NotificationCompat.Builder notificationBuilder = null;
@ -65,7 +71,6 @@ public class AutomationService extends Service implements OnInitListener
lockSoundChangesEnd = Calendar.getInstance();
lockSoundChangesEnd.add(Calendar.MINUTE, Settings.lockSoundChangesInterval);
// ActivityMainScreen.getActivityMainScreenInstance().updateMainScreen();
}
public void checkLockSoundChangesTimeElapsed()
@ -109,18 +114,6 @@ public class AutomationService extends Service implements OnInitListener
public boolean checkStartupRequirements(Context context, boolean startAtBoot)
{
// if (!ActivityPermissions.havePermission(ActivityPermissions.writeExternalStoragePermissionName, AutomationService.this))
// {
// /*
// Don't have permission to access external storage. This is a show stopper as
// the configuration file is stored on external storage.
// */
// Miscellaneous.logEvent("e", "Permission", "Don't have permission to access external storage. Will request it now.", 4);
//// Toast.makeText(AutomationService.this, getResources().getString(R.string.appRequiresPermissiontoAccessExternalStorage), Toast.LENGTH_LONG).show();
// ActivityPermissions.requestSpecificPermission(ActivityPermissions.writeExternalStoragePermissionName);
// return false;
// }
if(Build.VERSION.SDK_INT >= 28)
{
if (!ActivityPermissions.havePermission(Manifest.permission.FOREGROUND_SERVICE, AutomationService.this))
@ -135,9 +128,14 @@ public class AutomationService extends Service implements OnInitListener
}
}
if (PointOfInterest.getPointOfInterestCollection() == null | PointOfInterest.getPointOfInterestCollection().size() == 0
|
Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0
if (
PointOfInterest.getPointOfInterestCollection() == null
||
PointOfInterest.getPointOfInterestCollection().size() == 0
||
Rule.getRuleCollection() == null
||
Rule.getRuleCollection().size() == 0
)
{
if (startAtBoot)
@ -173,7 +171,7 @@ public class AutomationService extends Service implements OnInitListener
}
//if still no POIs...
if (Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0)
if (Rule.getRuleCollection() == null || Rule.getRuleCollection().size() == 0)
{
Miscellaneous.logEvent("w", "AutomationService", context.getResources().getString(R.string.serviceWontStart), 1);
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
@ -199,13 +197,13 @@ public class AutomationService extends Service implements OnInitListener
if (checkStartupRequirements(this, startAtBoot))
{
Miscellaneous.logEvent("i", "Service", this.getResources().getString(R.string.logServiceStarting) + " VERSION_CODE: " + BuildConfig.VERSION_CODE + ", VERSION_NAME: " + BuildConfig.VERSION_NAME + ", flavor: " + BuildConfig.FLAVOR, 1);
Miscellaneous.logEvent("i", "Service", ActivityMaintenance.getSystemInfo(), 1);
Miscellaneous.logEvent("i", "Service", ActivityControlCenter.getSystemInfo(), 1);
startUpRoutine();
Intent myIntent = new Intent(this, ActivityMainTabLayout.class);
myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0);
notificationBuilder = createDefaultNotificationBuilder();
notificationBuilder = createServiceNotificationBuilder();
updateNotification();
@ -220,6 +218,13 @@ public class AutomationService extends Service implements OnInitListener
// Actions.setData(true);
// ********** Test area **********
/*
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
@ -316,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()
@ -365,9 +376,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Features disabled because of rule " + rule, 5);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(1010, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
Miscellaneous.createDismissibleNotificationWithDelay(1010, null, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
}
@ -389,9 +400,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Background location disabled because Google to blame.", 5);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(3300, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
Miscellaneous.createDismissibleNotificationWithDelay(3300, null, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
}
@ -411,9 +422,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Background location disabled because Google to blame.", 5);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(2200, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
Miscellaneous.createDismissibleNotificationWithDelay(2200, null, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
@ -482,7 +493,7 @@ public class AutomationService extends Service implements OnInitListener
return builder;
}
protected static NotificationCompat.Builder createDefaultNotificationBuilder()
protected static NotificationCompat.Builder createServiceNotificationBuilder()
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -490,14 +501,14 @@ public class AutomationService extends Service implements OnInitListener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_LOW);
// chan.setLightColor(Color.BLUE);
chan.enableVibration(false);
chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel channel = Miscellaneous.getNotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE);
// channel.setLightColor(Color.BLUE);
channel.enableVibration(false);
channel.setSound(null, null);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID_SERVICE);
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
@ -576,7 +587,7 @@ public class AutomationService extends Service implements OnInitListener
String textToDisplay = bodyText + " " + lastRuleString;
if(notificationBuilder == null)
notificationBuilder = createDefaultNotificationBuilder();
notificationBuilder = createServiceNotificationBuilder();
notificationBuilder.setContentText(textToDisplay);
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));

View File

@ -8,7 +8,7 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -16,6 +16,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@ -23,6 +25,7 @@ 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;
@ -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;
@ -83,7 +88,10 @@ import java.text.SimpleDateFormat;
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;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@ -98,13 +106,10 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.documentfile.provider.DocumentFile;
import static android.provider.CalendarContract.CalendarCache.URI;
import static com.jens.automation2.AutomationService.NOTIFICATION_CHANNEL_ID;
import static com.jens.automation2.AutomationService.channelName;
public class Miscellaneous extends Service
{
protected static String writeableFolderStringCache = null;
@ -630,30 +635,46 @@ public class Miscellaneous extends Service
}
if(source.contains("[notificationTitle]"))
{
if(NotificationListener.getLastNotification() != null)
{
String notificationTitle = NotificationListener.getLastNotification().getTitle();
if(notificationTitle != null && notificationTitle.length() > 0)
if (notificationTitle != null && notificationTitle.length() > 0)
source = source.replace("[notificationTitle]", notificationTitle);
else
{
source = source.replace("notificationTitle unknown", notificationTitle);
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationTitle was empty.", 3);
}
}
else
{
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
if(source.contains("[notificationText]"))
{
if(NotificationListener.getLastNotification() != null)
{
String notificationText = NotificationListener.getLastNotification().getText();
if(notificationText != null && notificationText.length() > 0)
if (notificationText != null && notificationText.length() > 0)
source = source.replace("[notificationText]", notificationText);
else
{
source = source.replace("notificationText unknown", notificationText);
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationText was empty.", 3);
}
}
else
{
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
// Miscellaneous.logEvent("i", "URL after replace", source);
@ -877,7 +898,7 @@ public class Miscellaneous extends Service
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void createDismissableNotificationWithDelay(long delay, String textToDisplay, int notificationId, PendingIntent pendingIntent)
public static void createDismissibleNotificationWithDelay(long delay, String title, String textToDisplay, int notificationId, String notificationChannelId, PendingIntent pendingIntent)
{
/*
Now what's this about?
@ -903,7 +924,7 @@ public class Miscellaneous extends Service
catch(Exception e)
{}
createDismissableNotification(textToDisplay, notificationId, pendingIntent);
createDismissibleNotification(title, textToDisplay, notificationId, true, notificationChannelId, pendingIntent);
return null;
}
@ -924,40 +945,88 @@ public class Miscellaneous extends Service
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void createDismissableNotification(String textToDisplay, int notificationId, PendingIntent pendingIntent)
public static void createDismissibleNotification(String title, String textToDisplay, int notificationId, boolean vibrate, String notificationChannelId, PendingIntent pendingIntent)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
createDismissableNotificationSdk26(textToDisplay, notificationId, pendingIntent);
createDismissibleNotificationSdk26(title, textToDisplay, notificationId, vibrate, notificationChannelId, pendingIntent);
return;
}
NotificationManager mNotificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder dismissableNotificationBuilder = createDismissableNotificationBuilder(pendingIntent);
dismissableNotificationBuilder.setContentText(textToDisplay);
dismissableNotificationBuilder.setContentIntent(pendingIntent);
dismissableNotificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
dismissableNotificationBuilder.setAutoCancel(true);
NotificationCompat.Builder dismissibleNotificationBuilder = createDismissibleNotificationBuilder(vibrate, notificationChannelId, pendingIntent);
Notification dismissableNotification = dismissableNotificationBuilder.build();
if(title == null)
dismissibleNotificationBuilder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
else
dismissibleNotificationBuilder.setContentTitle(title);
mNotificationManager.notify(notificationId, dismissableNotification);
dismissibleNotificationBuilder.setContentText(textToDisplay);
dismissibleNotificationBuilder.setContentIntent(pendingIntent);
dismissibleNotificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
dismissibleNotificationBuilder.setAutoCancel(true);
/*NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle("Notification!") // title for notification
.setContentText("Hello word") // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, dismissableNotification);*/
if(notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_RULES))
dismissibleNotificationBuilder.setSmallIcon(R.drawable.info);
Notification dismissibleNotification = dismissibleNotificationBuilder.build();
mNotificationManager.notify(notificationId, dismissibleNotification);
}
static void createDismissableNotificationSdk26(String textToDisplay, int notificationId, PendingIntent pendingIntent)
@RequiresApi(api = Build.VERSION_CODES.O)
static NotificationChannel findExistingChannel(List<NotificationChannel> channels, String channelId)
{
for(NotificationChannel c : channels)
{
if(c.getId().equals(channelId))
return c;
}
return null;
}
@RequiresApi(api = Build.VERSION_CODES.O)
static NotificationChannel getNotificationChannel(String channelId)
{
NotificationManager nm = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
List<NotificationChannel> channels = nm.getNotificationChannels();
if(!Settings.hasBeenDone(Settings.constNotificationChannelCleanupApk118) && BuildConfig.VERSION_CODE < 120)
{
// Perform a one-time cleanup of notification channels as they have been redesigned.
for(NotificationChannel c : channels)
nm.deleteNotificationChannel(c.getId());
Settings.considerDone(Settings.constNotificationChannelCleanupApk118);
Settings.writeSettings(Miscellaneous.getAnyContext());
}
NotificationChannel channel = findExistingChannel(channels, channelId);
if(channel == null)
{
switch (channelId)
{
case AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, AutomationService.NOTIFICATION_CHANNEL_NAME_SERVICE, NotificationManager.IMPORTANCE_LOW);
break;
case AutomationService.NOTIFICATION_CHANNEL_ID_FUNCTIONALITY:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_FUNCTIONALITY, AutomationService.NOTIFICATION_CHANNEL_NAME_FUNCTIONALITY, NotificationManager.IMPORTANCE_HIGH);
break;
case AutomationService.NOTIFICATION_CHANNEL_ID_RULES:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_RULES, AutomationService.NOTIFICATION_CHANNEL_NAME_RULES, NotificationManager.IMPORTANCE_HIGH);
break;
default:
break;
}
}
return channel;
}
static void createDismissibleNotificationSdk26(String title, String textToDisplay, int notificationId, boolean vibrate, String notificationChannelId, PendingIntent pendingIntent)
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -965,29 +1034,44 @@ public class Miscellaneous extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Functionality warnings", NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE);
chan.enableVibration(false);
// chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel notificationChannel = getNotificationChannel(notificationChannelId);
// notificationChannel.setLightColor(Color.BLUE);
notificationChannel.enableVibration(vibrate);
try
{
Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// Uri notificationSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE+ "://" +mContext.getPackageName()+"/"+R.raw.apple_ring));
// Ringtone r = RingtoneManager.getRingtone(Miscellaneous.getAnyContext(), notification);
AudioAttributes.Builder b = new AudioAttributes.Builder();
b.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN);
notificationChannel.setSound(notificationSound, b.build());
}
catch (Exception e)
{
Miscellaneous.logEvent("i", "Notification", Log.getStackTraceString(e), 2);
}
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), notificationChannel.getId());
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
// builder.setCategory(Notification.CATEGORY_SERVICE);
builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(pendingIntent);
if(title == null)
builder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
else
builder.setContentTitle(title);
builder.setOnlyAlertOnce(true);
if(Settings.showIconWhenServiceIsRunning)
if(Settings.showIconWhenServiceIsRunning && notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.ic_launcher);
else if(!notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.info);
builder.setContentText(textToDisplay);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
@ -995,7 +1079,6 @@ public class Miscellaneous extends Service
NotificationManager notificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
// Intent notifyIntent = new Intent(context, notification.class);
// notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//
@ -1017,7 +1100,7 @@ public class Miscellaneous extends Service
// notificationManager.notify(1, notification);
}
protected static NotificationCompat.Builder createDismissableNotificationBuilder(PendingIntent myPendingIntent)
protected static NotificationCompat.Builder createDismissibleNotificationBuilder(boolean vibrate, String notificationChannelId, PendingIntent myPendingIntent)
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -1025,14 +1108,14 @@ public class Miscellaneous extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE);
// chan.enableVibration(false);
// chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel notificationChannel = getNotificationChannel(notificationChannelId);
// notificationChannel.setLightColor(Color.BLUE);
notificationChannel.enableVibration(vibrate);
// notificationChannel.setSound(null, null);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), notificationChannelId);
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
@ -1110,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);
@ -1122,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();
@ -1142,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;
@ -1593,4 +1785,117 @@ public class Miscellaneous extends Service
return formattedDate;
}
public static boolean arraySearch(String[] haystack, String needle, boolean caseSensitive, boolean matchFullLine)
{
if(matchFullLine)
{
if(caseSensitive)
{
for (String s : haystack)
{
if (s.equals(needle))
return true;
}
}
else
{
for (String s : haystack)
{
if (s.toLowerCase().equals(needle.toLowerCase()))
return true;
}
}
}
else
{
if(caseSensitive)
{
for (String s : haystack)
{
if (s.contains(needle))
return true;
}
}
else
{
for (String s : haystack)
{
if (s.toLowerCase().contains(needle.toLowerCase()))
return true;
}
}
}
return false;
}
public static boolean arraySearch(ArrayList<String> requestList, String needle, boolean caseSensitive, boolean matchFullLine)
{
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();
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), usingRule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
{
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else
{
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;
@ -51,8 +53,11 @@ public class ReceiverCoordinator
HeadphoneJackListener.class,
//NfcReceiver.class,
NoiseListener.class,
//NotificationListener.class,
PhoneStatusListener.class,
ProcessListener.class,
MediaPlayerListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
};
}
@ -69,6 +74,7 @@ public class ReceiverCoordinator
NoiseListener.class,
PhoneStatusListener.class,
ProcessListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
};
}
@ -132,12 +138,6 @@ public class ReceiverCoordinator
Miscellaneous.logEvent("w", "Error in new model", Log.getStackTraceString(e), 3);
}
// if(Settings.useAccelerometerForPositioning && !Miscellaneous.isAndroidEmulator())
// {
// accelerometerHandler = new AccelerometerHandler();
// mySensorActivity = new SensorActivity(this);
// }
// startPhoneStateListener
PhoneStatusListener.startPhoneStatusListener(AutomationService.getInstance()); // also used to mute anouncements during calls
@ -163,7 +163,7 @@ public class ReceiverCoordinator
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.noiseLevel))
NoiseListener.startNoiseListener(AutomationService.getInstance());
// startNoiseListener
// startProcessListener
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.process_started_stopped))
ProcessListener.startProcessListener(AutomationService.getInstance());
@ -182,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()
@ -203,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
@ -241,7 +246,7 @@ public class ReceiverCoordinator
// timeFrame -> too inexpensive to shutdown
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
{
if(BatteryReceiver.haveAllPermission())
BatteryReceiver.startBatteryReceiver(AutomationService.getInstance());
@ -273,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

@ -20,6 +20,7 @@ public class Settings implements SharedPreferences
public static final String zipFileName = "automation.zip";
public static final String constNewsOptInDone ="newsOptInDone";
public static final String constNotificationChannelCleanupApk118 ="notificationChannelCleanupApk118";
public static long minimumDistanceChangeForGpsUpdate;
public static long minimumDistanceChangeForNetworkUpdate;
@ -65,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;
@ -79,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)
@ -260,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);
@ -326,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();
@ -542,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,9 +38,66 @@ 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;
final static String anyAppString = "-1";
public boolean applies(Object triggeringObject, Context context)
{
boolean result = true;
@ -121,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;
}
@ -163,15 +232,13 @@ public class Trigger
{
if(getParentRule().getLastExecution() == null || sbn.getPostTime() > this.getParentRule().getLastExecution().getTimeInMillis())
{
String notificationApp = sbn.getPackageName();
String notificationTitle = null;
String notificationText = null;
NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn);
Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5);
Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().getName() + ": " + sn.toString(), 5);
if (!myApp.equals("-1"))
if (!myApp.equals(anyAppString))
{
if (!notificationApp.equalsIgnoreCase(myApp))
if (!myApp.equalsIgnoreCase(sn.getApp()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5);
continue;
@ -179,6 +246,9 @@ public class Trigger
}
else
{
/*
Notifications from Automation are disregarded to avoid infinite loops.
*/
if(myApp.equals(BuildConfig.APPLICATION_ID))
{
return false;
@ -190,15 +260,10 @@ public class Trigger
https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications
*/
Bundle extras = sbn.getNotification().extras;
// T I T L E
if (extras.containsKey(EXTRA_TITLE))
notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE);
if (!StringUtils.isEmpty(requiredTitle))
{
if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle))
if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5);
continue;
@ -208,13 +273,9 @@ public class Trigger
Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5);
// T E X T
if (extras.containsKey(EXTRA_TEXT))
notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT);
if (!StringUtils.isEmpty(requiredText))
{
if (!Miscellaneous.compare(myTextDir, requiredText, notificationText))
if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5);
continue;
@ -243,7 +304,7 @@ public class Trigger
String title = NotificationListener.getLastNotification().getTitle();
String text = NotificationListener.getLastNotification().getText();
if (!myApp.equals("-1"))
if (!myApp.equals(anyAppString))
{
if (!app.equalsIgnoreCase(myApp))
return false;
@ -277,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];
@ -314,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);
@ -538,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);
@ -944,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);
@ -956,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);
@ -997,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, 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";
@ -1073,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()
{
@ -1466,7 +1492,7 @@ public class Trigger
StringBuilder triggerBuilder = new StringBuilder();
String appString;
if (app.equalsIgnoreCase("-1"))
if (app.equalsIgnoreCase(anyAppString))
appString = Miscellaneous.getAnyContext().getResources().getString(R.string.anyApp);
else
appString = "app " + app;
@ -1486,7 +1512,7 @@ public class Trigger
}
else
{
setTriggerParameter2("-1" + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split);
setTriggerParameter2(anyAppString + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split);
}
break;
case deviceOrientation:
@ -1498,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;
@ -1551,10 +1602,6 @@ public class Trigger
{
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

@ -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

@ -217,6 +217,8 @@ public class NfcReceiver
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
if(ndefMessage != null)
{
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records)
{
@ -232,6 +234,7 @@ public class NfcReceiver
}
}
}
}
return null;
}

View File

@ -1,9 +1,15 @@
package com.jens.automation2.receivers;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.annotation.RequiresApi;
@ -19,9 +25,10 @@ import java.util.Calendar;
@SuppressLint("OverrideAbstract")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationListener extends NotificationListenerService
public class NotificationListener extends NotificationListenerService// implements AutomationListenerInterface
{
static Calendar lastResponseToNotification = null;
static boolean listenerRunning = false;
static NotificationListener instance;
static SimpleNotification lastNotification = null;
@ -37,6 +44,8 @@ public class NotificationListener extends NotificationListenerService
// a bitmap to be used instead of the small icon when showing the notification payload
public static final String EXTRA_LARGE_ICON = "android.largeIcon";
protected static IntentFilter notificationReceiverIntentFilter = null;
public static SimpleNotification getLastNotification()
{
return lastNotification;
@ -78,16 +87,7 @@ public class NotificationListener extends NotificationListenerService
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
{
String app = sbn.getPackageName();
String title = sbn.getNotification().extras.getString(EXTRA_TITLE);
String text = sbn.getNotification().extras.getString(EXTRA_TEXT);
lastNotification = new SimpleNotification();
lastNotification.publishTime = Miscellaneous.calendarFromLong(sbn.getPostTime());
lastNotification.created = created;
lastNotification.app = app;
lastNotification.title = title;
lastNotification.text = text;
lastNotification = convertNotificationToSimpleNotification(created, sbn);
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification);
for (int i = 0; i < ruleCandidates.size(); i++)
@ -100,6 +100,95 @@ public class NotificationListener extends NotificationListenerService
return false;
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static SimpleNotification convertNotificationToSimpleNotification(boolean created, StatusBarNotification input)
{
String app = input.getPackageName();
String title = "";
String text = "";
Bundle extras = input.getNotification().extras;
try
{
if (extras.containsKey(EXTRA_TITLE))
title = extras.getString(EXTRA_TITLE).toString();
}
catch (NullPointerException e)
{
// https://www.b4x.com/android/forum/threads/solved-reading-statusbarnotifications-extras.64416/
// Some notifications have an empty title, like KDE connect
if(extras.containsKey(EXTRA_TITLE) && extras.get(EXTRA_TITLE) != null)
title = extras.get(EXTRA_TITLE).toString();
}
try
{
if (extras.containsKey(EXTRA_TEXT))
text = extras.getString(EXTRA_TEXT).toString();
}
catch (NullPointerException e)
{
// in stacked notifications the "surrounding" element has no text, only a title
if (extras.containsKey(EXTRA_TEXT) && extras.get(EXTRA_TEXT) != null)
text = extras.get(EXTRA_TEXT).toString();
}
SimpleNotification returnNotification = new SimpleNotification();
returnNotification.publishTime = Miscellaneous.calendarFromLong(input.getPostTime());
returnNotification.created = created;
returnNotification.app = app;
returnNotification.title = title;
returnNotification.text = text;
return returnNotification;
}
/*@Override
public void startListener(AutomationService automationService)
{
if(instance == null)
instance = new NotificationListener();
if(notificationReceiverIntentFilter == null)
{
notificationReceiverIntentFilter = new IntentFilter();
notificationReceiverIntentFilter.addAction("android.service.notification.NotificationListenerService");
}
try
{
if(!listenerRunning)
{
Miscellaneous.logEvent("i", "NotificationListener", "Starting NotificationListener", 4);
listenerRunning = true;
AutomationService.getInstance().registerReceiver(instance, notificationReceiverIntentFilter);
}
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "BluetoothReceiver", "Error starting BluetoothReceiver: " + Log.getStackTraceString(ex), 3);
}
}
@Override
public void stopListener(AutomationService automationService)
{
}
@Override
public boolean isListenerRunning()
{
return false;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[0];
}*/
public static class SimpleNotification
{
boolean created;
@ -155,6 +244,18 @@ public class NotificationListener extends NotificationListenerService
{
this.text = text;
}
@Override
public String toString()
{
return "SimpleNotification{" +
"created=" + created +
", publishTime=" + publishTime +
", app='" + app + '\'' +
", title='" + title + '\'' +
", text='" + text + '\'' +
'}';
}
}
@Override
@ -168,4 +269,13 @@ public class NotificationListener extends NotificationListenerService
{
super.onListenerDisconnected();
}
public void dismissNotification(StatusBarNotification sbn)
{
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
else
cancelNotification(sbn.getKey());
}
}

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

@ -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,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>

View File

@ -16,14 +16,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:text="@string/settings"
android:text="@string/controlCenter"
android:layout_marginBottom="@dimen/default_margin"/>
<Button
android:id="@+id/bMoreSettings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/moreSettings" />
android:text="@string/settings" />
<ImageView
android:layout_width="match_parent"
@ -83,11 +83,25 @@
android:layout_margin="@dimen/default_margin"
android:background="#aa000000" />
<CheckBox
android:id="@+id/chkShareConfigAndLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/shareConfigAndLogFilesWithDev" />
<Button
android:id="@+id/bShareConfigAndLog"
android:id="@+id/bSendEmailToDev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/shareConfigAndLogFilesWithDev" />
android:text="@string/sendEmailToDev" />
<ImageView
android:layout_width="match_parent"
android:layout_span="2"
android:layout_height="1dp"
android:layout_margin="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:id="@+id/tvFileStoreLocation"

View File

@ -0,0 +1,155 @@
<?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:text="@string/closeNotifications"
android:textSize="25dp"
android:layout_marginBottom="@dimen/default_margin" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/notificationCloseActionExplanation" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/application" />
<LinearLayout
android:orientation="vertical"
android:layout_marginHorizontal="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/etActivityOrActionPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/anyApp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/bSelectApp"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/selectApplication" />
</LinearLayout>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/title" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerTitleDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etNotificationTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/text" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerTextDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etNotificationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>>
</TableLayout>
<Button
android:id="@+id/bSaveActionCloseNotification"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

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

@ -0,0 +1,90 @@
<?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:text="@string/createNotification"
android:textSize="25dp"
android:layout_marginBottom="@dimen/default_margin" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/title" />
<EditText
android:id="@+id/etNotificationTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</TableRow>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/text" />
<EditText
android:id="@+id/etNotificationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</TableRow>
</TableLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvLegend"
android:layout_width="match_parent"
android:layout_height="0dip"
android:text="@string/urlLegend" />
</ScrollView>
<Button
android:id="@+id/bSaveActionNotification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
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

@ -52,6 +52,15 @@
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileWarning"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textColor="@color/lightRed"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -96,6 +96,13 @@
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
@ -165,7 +172,7 @@
</TableLayout>
<Button
android:id="@+id/bSaveTriggerNotification"
android:id="@+id/bSaveActionCloseNotification"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

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

@ -293,5 +293,17 @@
</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"
@ -204,6 +204,34 @@
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"
android:layout_height="wrap_content"
@ -327,11 +355,11 @@
android:text="@string/privacy" />
<Button
android:id="@+id/bSettings"
android:id="@+id/bControlCenter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:text="@string/settings" />
android:text="@string/controlCenter" />
<Button
android:id="@+id/bDonate"
@ -341,6 +369,13 @@
android:layout_gravity="top"
android:text="@string/donate" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:gravity="center_horizontal"
android:text="@string/emailContactNotice" />
</LinearLayout>
</LinearLayout>

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>
@ -57,7 +57,7 @@
<string name="end">Ende</string>
<string name="save">Speichern</string>
<string name="urlToTrigger">URL, die ausgelöst werden soll:</string>
<string name="urlLegend">Variablen:\nSie können die folgenden Variablen verwenden. Vor dem Auslösen werden sie mit dem entsprechenden Wert Ihres Geräts ersetzt. Die Klammern müssen in den Text mit aufgenommen werden.\n\n[uniqueid] - Die Unique ID Ihres Geräts\n[serialnr] - Die Seriennummer Ihres Geräts\n[latitude] - Ihr gegenwärtiger Breitengrad\n[longitude] - Ihr gegenwärtiger Längengrad\n[phonenr] - Nummer des letzten ein- oder ausgehenden Anrufs\n[d] - Tag des Monats, 2-stellig mit führender Null\n[m] - Monat als Zahl, mit führenden Nullen\n[Y] - Vierstellige Jahreszahl\n[h] - Stunde im 12-Stunden-Format, mit führenden Nullen\n[H] - Stunde im 24-Stunden-Format, mit führenden Nullen\n[i] - Minuten, mit führenden Nullen\n[s] - Sekunden, mit führenden Nullen\n[ms] - milliseconds\n[notificationTitle] - Titel der letzten Benachrichtigung\n[notificationText] - Text der letzten Benachrichtigung</string>
<string name="urlLegend">Variablen:\nSie können die folgenden Variablen verwenden. Vor dem Auslösen werden sie mit dem entsprechenden Wert Ihres Geräts ersetzt. Die Klammern müssen in den Text mit aufgenommen werden.\n\n[uniqueid] - Die Unique ID Ihres Geräts\n[serialnr] - Die Seriennummer Ihres Geräts (&lt; Android 9)\n[latitude] - Ihr gegenwärtiger Breitengrad\n[longitude] - Ihr gegenwärtiger Längengrad\n[phonenr] - Nummer des letzten ein- oder ausgehenden Anrufs\n[d] - Tag des Monats, 2-stellig mit führender Null\n[m] - Monat als Zahl, mit führenden Nullen\n[Y] - Vierstellige Jahreszahl\n[h] - Stunde im 12-Stunden-Format, mit führenden Nullen\n[H] - Stunde im 24-Stunden-Format, mit führenden Nullen\n[i] - Minuten, mit führenden Nullen\n[s] - Sekunden, mit führenden Nullen\n[ms] - milliseconds\n[notificationTitle] - Titel der letzten Benachrichtigung\n[notificationText] - Text der letzten Benachrichtigung</string>
<string name="wifi">WLAN</string>
<string name="activating">Aktiviere</string>
<string name="deactivating">Deaktiviere</string>
@ -403,7 +403,7 @@
<string name="startNewThreadForRuleExecution">Für Regelaktivierung neuen Thread starten.</string>
<string name="newThreadRules">Neuer Thread</string>
<string name="showIcon">Symbol</string>
<string name="showIconWhenServiceIsRunning">Symbol anzeigen, wenn Dienst läuft (verstecken funktioniert nur unterhalb Android 7)</string>
<string name="showIconWhenServiceIsRunning">Symbol anzeigen, wenn Dienst läuft (verstecken funktioniert nur unterhalb Android 7). Wenn Sie auf einer höheren Version sind, gehen Sie in die System Einstellungen, dann Automation und dann Benachrichtigungen. Deaktivieren Sie die \"Service notification\".</string>
<string name="ruleHistory">Regel Historie (letzte zuerst):</string>
<string name="someOptionsNotAvailableYet">Manche Optionen sind deaktiviert, da sie noch nicht funktionieren. Sie kommen in einer späteren Programmversion dazu.</string>
<string name="lockSoundChanges">Tonänderungen sperren</string>
@ -532,7 +532,7 @@
<string name="fileDoesNotExist">Datei existiert nicht.</string>
<string name="noFileManageInstalled">Kein Dateimanager installiert.</string>
<string name="alwaysPlayExplanation">Wenn diese Einstellung aktiv ist, wird der Ton immer abgespielt. Wenn die Einstellung inaktiv ist, wird der Ton nur dann abgespielt, wenn das Telefon weder auf stumm noch auf Vibration steht, d.h. Klingeltöne aktiv sind. Allerdings hat es keinen Einfluß auf die Medien-Lautstärke. D.h., wenn diese stumm ist, werden Sie so oder so nichts zu hören bekommen.</string>
<string name="shareConfigAndLogFilesWithDev">Konfigurations- und Logdatei mit Entwickler teilen (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Konfigurations- und Logdateien anhängen</string>
<string name="shareConfigAndLogExplanation">Dies wird eine neue Email öffnen mit Konfigurations- und Logdateien als Zip-Anhang. Sie wird nicht automatisch versendet. D.h. Sie können so z.B. auch den Adressaten zu sich selbst ändern.</string>
<string name="notificationTriggerExplanation">Dieser Auslöser reagiert auf Benachrichtigungen anderer Anwendung im Benachrichtigungsbereich von Android (oder wenn diese geschlossen werden). Sie können eine bestimmte Anwendung festlegen, von die Nachricht stammen muß. Wenn nicht, zählt jede Benachrichtigung. Sie können auch Zeichenketten für Titel oder Nachrichteninhalt festlegen, die enthalten sein müssen. Die Groß-/Kleinschreibung wird hierbei nicht berücksichtigt.</string>
<string name="addParameters">Parameter hinzufügen</string>
@ -648,7 +648,7 @@
<string name="profileNotActive">Profil %1$s ist nicht aktiv</string>
<string name="profileTriggerCheckSettings">Wenn dieses Häkchen nicht gesetzt ist, wird nur geprüft, ob das ausgewählte Profil zuletzt aktiviert wurde. Es ist egal, ob Audio-Einstellungen von außerhalb verändert wurden.\nWenn das Häkchen aber gesetzt ist, müssen die aktuellen Audio-Einstellungen auch wirklich genau so gesetzt sein, wie im Profil definiert. ACHTUNG: Der Klingelton selbst kann derzeit noch nicht überprüft werden.</string>
<string name="profileCouldNotBeDeleted">Profil konnte nicht gelöscht werden.</string>
<string name="ruleXIsUsingProfileY">Dieses Profil kann nicht gelöscht werden. Regel %s$1 verwendet noch Profil %s$2.</string>
<string name="ruleXIsUsingProfileY">Dieses Profil kann nicht gelöscht werden. Regel %1$s verwendet noch Profil %2$s.</string>
<string name="noRepetition">keine Wiederholung</string>
<string name="usingAuthentication">mit Authentifizierung</string>
<string name="toNumber">zu Nummer</string>
@ -659,4 +659,45 @@
<string name="pickActivityManually">Manuell auswählen</string>
<string name="launcherOrManualExplanation">Einfacher Modus: Automation kann versuchen, die Start-Activity des Zielprogramms automatisch zu finden.\nAlternativ können Sie die gewünschte Activity auch manuell auswählen.\nWelche Variante möchten Sie?</string>
<string name="launcherNotFound">Eine Start-Activity dieser Anwendung konnte nicht gefunden werden. Sie müssen manuell eine auswählen.</string>
<string name="enterTitle">Geben Sie einen Titel ein.</string>
<string name="enterText">Geben Sie einen Text ein.</string>
<string name="info">Info</string>
<string name="createNotification">Benachrichtigung erstellen</string>
<string name="profileWasNotFound">Das Profil, das in dieser Regel referenziert wird, existiert scheinbar nicht mehr. Das alphabetisch erste wurde stattdessen ausgewählt.</string>
<string name="closeNotifications">Benachrichtigung(en) schließen</string>
<string name="comparisonCaseInsensitive">Groß-/Kleinschreibung ist egal.</string>
<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

@ -358,12 +358,12 @@
<string name="networkAccuracy">Red exactitud [m]</string>
<string name="minimumTimeForLocationUpdates">Tiempo mínimo para cambio en milisegundos para actualizar posición</string>
<string name="timeForUpdate">Tiempo para actualizar [milisegundos]</string>
<string name="urlLegend">Variables: Puede usar esas variables. Mientras ejecuta van a sustituir con los valores correspondientes en su dispositivo. Incluya las paréntecis en su texto. [uniqueid] - el número único de su dispositivo [serialnr] - el número de serie de su dispositivo [latitude] - su latitud [longitude] - su longitud [phonenr] - Ùltimo número de llamada realizada tanto de salida como entrante [d] - Dia del mes, 2 digitos con cero al comienzo [m] - número del mes, 2 digitos con cero al comienzo [Y] - Número del año, 4 digitos [h] - Hora, formato 12 horas con cero al comienzo [H] - Hora, formato 24 horas con cero al comienzo [i] - Minutos con cero al comienzo [s] - Segundos con cero al comienzo [ms] - milisegundos [notificationTitle] - Título de la última notificación [notificationText] - Texto de la última notificación</string>
<string name="urlLegend">Variables: Puede usar esas variables. Mientras ejecuta van a sustituir con los valores correspondientes en su dispositivo. Incluya las paréntecis en su texto.\n\n[uniqueid] - el número único de su dispositivo\n[serialnr] - el número de serie de su dispositivo (&lt; Android 9)\n[latitude] - su latitud\n[longitude] - su longitud\n[phonenr] - Ùltimo número de llamada realizada tanto de salida como entrante\n[d] - Dia del mes, 2 digitos con cero al comienzo\n[m] - número del mes, 2 digitos con cero al comienzo\n[Y] - Número del año, 4 digitos\n[h] - Hora, formato 12 horas con cero al comienzo\n[H] - Hora, formato 24 horas con cero al comienzo\n[i] - Minutos con cero al comienzo\n[s] - Segundos con cero al comienzo\n[ms] - milisegundos\n[notificationTitle] - Título de la última notificación\n[notificationText] - Texto de la última notificación</string>
<string name="screenRotationAlreadyEnabled">Rotación del monitor todavia esta activado.</string>
<string name="screenRotationAlreadyDisabled">Rotación del monitor todavia esta desactivado.</string>
<string name="needLocationPermForWifiList">Se puede usar la lista de wifis conocidos para determinar los sitios en los cuales estuvo. Por eso el permiso de localización es necesario para cargar la lista de wifis. Si quiere elegir uno de la lista tiene que conceder el permiso. En caso contrario todavia puede introducir un nombre wifi manualmente.</string>
<string name="com.wireguard.android.permission.CONTROL_TUNNELS">Controlar conexiones de la app Wireguard</string>
<string name="shareConfigAndLogFilesWithDev">Enviar configuración y procotolo al desarollador (vía email).</string>
<string name="shareConfigAndLogFilesWithDev">Adjuntar configuración y procotolo.</string>
<string name="rootExplanation">Necesita permiso root para esta función. Después encienda la función \"ejecutar regla manualmente\" para presentar el permiso superuser dialogo. Es necesario elegir \"siempre permitir root para esta app\". En caso contrario la regla no puede funcionar en segundo plano.</string>
<string name="helpTextRules">Todas las condiciones están \"Y\"-conectadas. La regla solo va a aplicarse cuando todas las condiciones se aplican. Si quiere \"O\", cree otra regla.</string>
<string name="timeBetweenNoiseLevelMeasurementsSummary">Segundos entre dos ensayos de nivel de ruido</string>
@ -470,7 +470,7 @@
<string name="noMapsApplicationFound">Parece que no hay una aplicación de mapa en su dispositivo.</string>
<string name="soundMode">Modo de sonido de llamada.</string>
<string name="showIcon">Monstrar icono</string>
<string name="showIconWhenServiceIsRunning">Monstrar icono cuando el servicio esta activo (ocultando solo funciona antes Android 7)</string>
<string name="showIconWhenServiceIsRunning">Monstrar icono cuando el servicio esta activo (ocultando solo funciona antes Android 7). Si está en una versión superior, vaya a configuración del sistema, luego Automatización, luego notificaciones y deshabilite \"Service notification\".</string>
<string name="currentVolume">Volumen actual</string>
<string name="volumeTest">Calibrado de volumen</string>
<string name="permissionsTitle">Permisos necesarios</string>
@ -588,7 +588,7 @@
<string name="vibrate">Vibrar</string>
<string name="test">Probar</string>
<string name="VibrateExplanation">Elija la duración de la vibración, seguido de un coma y una duración de una pausa. Puedes concatenar tantos como quiere. Separelos con comas tambien. Por ejemplo el patrón 100,500,500,1000,100 va a vibrar 100, esperar 500, vibrar 500, esperar 1000, vibrar 100 ms. Si cree que una vibración está perdida, pruebe incrementar la pausa antes de esta vibración.</string>
<string name="pleaseEnterValidVibrationPattern">Por favor introduzca un patrón de vibración válido.</string>
<string name="pleaseEnterValidVibrationPattern">Por favor inserte un patrón de vibración válido.</string>
<string name="tabsPlacementSummary">Elija done la barra de tabs está puesto.</string>
<string name="intentDataComment">Si su parametro es de tipo Uri y especifica \"IntentData\" como nombre (minúscula/mayáscula no es importante), el parametro no está añadido como un parametro normal con puExtra(), pero estará añadido al intent con setData().</string>
<string name="locationEngineDisabledLong">Desafortunadamente su posición todavia no puede ser determinada. Gratitud va para Google por su sabiduria y amabilidad infinita.\n\nDejenme explicarselo mas. Comenzando con Android 10 un nuevo permiso se introdujo que es necesario para determinar la posición en el fondo (que es necesario para una app como esta). Aunque lo considero una buena idea, conlleva a una chicana para desarolladores.\n\nCuando se esta desarrollando una app se puede intentar calificar para este permiso mientras se sigue un catalogo de condiciones. Desafortunadamente nuevas versiones de mi app fueron rechazadas por un periodo de trés meses. Cumplé todas las condiciones, pero Google\'s mierda servicio para desarolladores afirmó que no. Despues de presentar pruebas, que cumplí con todo, recibí una respuesta de \"No puedo ayudarte mas.\". En algun momento me rendí.\n\nComo consecuencia la version Google Play todavia no sabe usar la locación como una condición. Mi única alternativa fue remover la applicación de Google Play.\n\nLo siento mucho, pero hicé todo lo posible para discutir con un support que no sabe aprobar la prueba de Turing repetidamente.\n\nLa noticia positiva: Usted todavia puede tener todo!\n\nAutomation ahora es open source y se puede encontrar en F-Droid. Es un app store que se preocupa por su privacidad - en vez de solo simular eso. Simplemente guarde su configuración, desinstale la app, instale la de F-Droid, restaure su configuración - terminado.\n\nCliquee aqui para averiguar más:</string>
@ -626,7 +626,7 @@
<string name="automationNotificationsIgnored">Si no elige una aplicación específica, sino que elige \"Cualquier aplicación\", las notificaciones de Automatización se ignorarán para evitar bucles.</string>
<string name="enterRepetitionTime">Debe insertar un valor positivo no decimal para el tiempo de repetición.</string>
<string name="elementSkipped">No se pudo leer un elemento del archivo de configuración. El archivoo puede haber sido creado por una versión más reciente del programa.</string>
<string name="enterValidNumbersIntoAllFields">Introduzca números válidos en todos los campos.</string>
<string name="enterValidNumbersIntoAllFields">Inserte números válidos en todos los campos.</string>
<string name="toleranceOf180OnlyAllowedIn2Fields">Se permite una tolerancia de 180 solo para 2 campos de tolerancia, no para todos los 3. De lo contrario, el disparador SIEMPRE se aplicaría.</string>
<string name="triggerWrong">Hay algo mal con este condición. No se pudo cargar correctamente.</string>
<string name="deviceOrientationTimeAcceptIntervalSummary">Aceptar nuevas señales de movimiento cada x milisegundos</string>
@ -646,7 +646,7 @@
<string name="recommendedForBetterReliability">Recomendado para una mejor fiabilidad</string>
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Excluir de la optimización de la batería</string>
<string name="profileTriggerCheckSettings">Si esta casilla de verificación no está desactivada, solo se marcará si el perfil seleccionado ha sido el último en activarse. No importa si alguna configuración relacionada con el audio se ha cambiado externamente.\nSin embargo, si la casilla de verificación está habilitada, la configuración de audio actual realmente debe ser como se define en el perfil. CUIDADO: La comprobación del archivo de tono de llamada no es compatible actualmente, todavía.</string>
<string name="ruleXIsUsingProfileY">No se puede eliminar este perfil. La regla %s$1 hace referencia al perfil %s$2.</string>
<string name="ruleXIsUsingProfileY">No se puede eliminar este perfil. La regla %1$s hace referencia al perfil %2$s.</string>
<string name="profileCouldNotBeDeleted">No se pudo eliminar el perfil.</string>
<string name="noRepetition">sin repetición</string>
<string name="usingAuthentication">uso de la autenticación</string>
@ -658,4 +658,45 @@
<string name="pickActivityManually">Eligir manualmente</string>
<string name="launcherOrManualExplanation">Modo facil: Automation puede probar identifcar el launcher activity del programa automaticamente.\nAlternativamente puede eligir una de las activities del programa manualmente.\nCual variante queria?</string>
<string name="launcherNotFound">No se puede encontrar una launcher activity. Tiene que elegir una manualmente.</string>
<string name="info">Info</string>
<string name="createNotification">Crear notificación</string>
<string name="enterTitle">Inserte un título.</string>
<string name="enterText">Inserte un texto.</string>
<string name="profileWasNotFound">El perfil utilizado en esta regla ya no parece existir. Se ha seleccionado el primero alfabéticamente.</string>
<string name="notificationCloseActionExplanation">Si no especifica ningún criterio, esta acción cerrará TODAS las notificaciones. Por lo tanto, se recomienda al menos especificar criterios para al menos 1 de la aplicación, título o texto.</string>
<string name="closeNotifications">Cerrar notificación(es)</string>
<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">Condividere i file di configurazione e di registro con lo sviluppatore (via e-mail).</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)</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\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>
@ -647,7 +647,7 @@
<string name="checkSettings">Controlla le impostazioni</string>
<string name="profileActive">profilo %1$s è attivo</string>
<string name="profileNotActive">profilo %1$s non attivo</string>
<string name="ruleXIsUsingProfileY">Impossibile eliminare questo profilo. La regola %s$1 fa riferimento al profilo %s$2.</string>
<string name="ruleXIsUsingProfileY">Impossibile eliminare questo profilo. La regola %1$s fa riferimento al profilo %2$s.</string>
<string name="profileCouldNotBeDeleted">Impossibile eliminare il profilo.</string>
<string name="noRepetition">nessuna ripetizione</string>
<string name="usingAuthentication">utilizzo dell\'autenticazione</string>
@ -659,4 +659,45 @@
<string name="pickActivityManually">Scegli manualmente</string>
<string name="launcherOrManualExplanation">Modalità semplice: l\'automazione può provare a identificare l\'attività di avvio del programma desiderato.\nIn alternativa puoi anche scegliere manualmente una delle attività dell\'applicazione.\nCosa vorresti?</string>
<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">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 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 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

@ -56,7 +56,7 @@
<string name="end">Einde</string>
<string name="save">Opslaan</string>
<string name="urlToTrigger">URL om te activeren:</string>
<string name="urlLegend">Variabelen:U kunt de volgende variabelen gebruiken. Bij het triggeren zullen ze worden vervangen door de corresponderende waarde op je apparaat. Zet de haakjes in uw tekst. \n[uniqueid] - Het unieke id van uw apparaat[serienummer] - Het serienummer van uw apparaat[latitude] - De breedtegraad van uw apparaat[longitude] - De lengtegraad van uw apparaat[phonenr] - Nummer van het laatste inkomende of uitgaande gesprek[d] - Dag van de maand, 2 cijfers met voorloopnullen[m] - Numerieke weergave van een maand, met voorloopnullen[Y] - een volledige numerieke weergave van een jaar, 4 cijfers[h] - 12-uurs indeling van een uur, met voorloopnullen[H] - 24-uurs indeling van een uur, met voorloopnullen[i] - minuten, met voorloopnullen[s] - seconden, met voorloopnullen[ms] - milliseconden[notificationTitle] - titel van de laatste melding[notificationText] - tekst van de laatste melding</string>
<string name="urlLegend">Variabelen:U kunt de volgende variabelen gebruiken. Bij het triggeren zullen ze worden vervangen door de corresponderende waarde op je apparaat. Zet de haakjes in uw tekst. \n[uniqueid] - Het unieke id van uw apparaat[serialnr] - Het serienummer van uw apparaat (&lt; Android 9)[latitude] - De breedtegraad van uw apparaat[longitude] - De lengtegraad van uw apparaat[phonenr] - Nummer van het laatste inkomende of uitgaande gesprek[d] - Dag van de maand, 2 cijfers met voorloopnullen[m] - Numerieke weergave van een maand, met voorloopnullen[Y] - een volledige numerieke weergave van een jaar, 4 cijfers[h] - 12-uurs indeling van een uur, met voorloopnullen[H] - 24-uurs indeling van een uur, met voorloopnullen[i] - minuten, met voorloopnullen[s] - seconden, met voorloopnullen[ms] - milliseconden[notificationTitle] - titel van de laatste melding[notificationText] - tekst van de laatste melding</string>
<string name="wifi">wifi</string>
<string name="activating">Activeren</string>
<string name="deactivating">Deactiveren</string>
@ -401,7 +401,7 @@
<string name="startNewThreadForRuleExecution">Start nieuw process voor activatie regel.</string>
<string name="newThreadRules">Nieuw process</string>
<string name="showIcon">Pictogram tonen</string>
<string name="showIconWhenServiceIsRunning">Pictogram tonen als de service draait (verbergen werkt alleen onder Android 7)</string>
<string name="showIconWhenServiceIsRunning">Pictogram tonen als de service draait (verbergen werkt alleen onder Android 7). Als u een hogere versie gebruikt, gaat u naar systeeminstellingen, vervolgens automatisering, vervolgens meldingen en schakelt u de \"Service notification\" uit.</string>
<string name="ruleHistory">Regelgeschiedenis (meest recente eerst):</string>
<string name="someOptionsNotAvailableYet">Sommige opties zijn uitgeschakeld omdat ze nog niet gebruikt kunnen worden. Ze zullen in een latere programmaversie worden geïntroduceerd.</string>
<string name="lockSoundChanges">Geluidswijzigingen vergrendelen</string>
@ -530,7 +530,7 @@
<string name="selectSoundFile">Selecteer geluidsbestand</string>
<string name="fileDoesNotExist">Bestand bestaat niet.</string>
<string name="noFileManageInstalled">Geen bestandsmanager geïnstalleerd.</string>
<string name="shareConfigAndLogFilesWithDev">Deel config en log bestanden met ontwikkelaar (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Config en log vastmaken</string>
<string name="shareConfigAndLogExplanation">Dit zal een nieuwe email starten met uw configuratie en log bestanden als zip bestand bijgevoegd. Het zal niet automatisch verzonden worden, je moet nog steeds op "verzenden" drukken. U kunt ook de ontvanger veranderen in bijvoorbeeld uzelf.</string>
<string name="startAppChoiceNote">Hier heeft u 2 algemene opties:. Je kunt een programma starten door een activiteit te selecteren. Stel je dit voor als het voorselecteren van een specifiek scherm/venster van een applicatie. Onthoud dat dit niet altijd zal werken. Dit komt omdat de vensters van een toepassing met elkaar kunnen interageren, bv. parameters doorgeven. Bij het botweg starten van een specifiek scherm heeft die interactie niet plaatsgevonden en kan het venster direct sluiten (waardoor het nooit echt getoond wordt). Probeer het desondanks! Je kunt een activiteitspad handmatig invoeren, maar het is aan te bevelen om de knop "Kiezen" te gebruiken. Als u besluit het pad handmatig in te voeren, voer dan in het bovenste veld de pakketnaam van de toepassing in en in het onderste veld het volledige pad van de activiteit.. Selectie door actie In tegenstelling tot het selecteren van een specifiek venster kunt u een programma ook door een actie starten. Dit is hetzelfde als roepen "Ik zou graag xyz willen" en als er een programma is geïnstalleerd dat u daarbij kan helpen, wordt het gestart. Een goed voorbeeld zou kunnen zijn start browser - je kunt er zelfs meerdere geïnstalleerd hebben (een is meestal de standaard). U moet dit handmatig invoeren, PackageName is hier optioneel. Houd in gedachten dat er geen variabelen zullen worden opgelost. Als je bijvoorbeeld de camera wilt starten met "MediaStore.ACTION_IMAGE_CAPTURE" zal dat niet werken. U moet een kijkje nemen in de Android documentatie en in plaats daarvan de werkelijke waarde van deze variabele gebruiken, die in dit voorbeeld zou zijn: "android.media.action.IMAGE_CAPTURE"</string>
<string name="errorRunningRule">Er is een fout opgetreden bij het uitvoeren van een regel.</string>
@ -645,7 +645,7 @@
<string name="profileActive">profile %1$s is actief</string>
<string name="profileNotActive">profile %1$s is niet actief</string>
<string name="profileTriggerCheckSettings">Als dit selectievakje niet is uitgeschakeld, wordt het alleen aangevinkt als het geselecteerde profiel het laatste is dat is geactiveerd. Het maakt niet uit of audiogerelateerde instellingen extern zijn gewijzigd.\nAls het selectievakje echter is ingeschakeld, moeten de huidige audio-instellingen echt worden gedefinieerd in het profiel. PAS OP: Het controleren van het beltoonbestand wordt momenteel nog niet ondersteund.</string>
<string name="ruleXIsUsingProfileY">Kan dit profiel niet verwijderen. Regel %s$1 verwijst naar het profiel %s$2.</string>
<string name="ruleXIsUsingProfileY">Kan dit profiel niet verwijderen. Regel %1$s verwijst naar het profiel %2$s.</string>
<string name="profileCouldNotBeDeleted">Profiel kan niet worden verwijderd.</string>
<string name="noRepetition">geen herhaling</string>
<string name="usingAuthentication">authenticatie gebruiken</string>
@ -657,4 +657,45 @@
<string name="pickActivityManually">Handmatig kiezen</string>
<string name="launcherNotFound">Een launcher-activiteit van deze app kon niet worden geïdentificeerd. U moet er handmatig een kiezen.</string>
<string name="launcherOrManualExplanation">Eenvoudige modus: Automatisering kan proberen de opstartactiviteit van het gewenste programma te identificeren.\nU kunt ook handmatig een van de activiteiten van de toepassing kiezen.\nWat wil je?</string>
<string name="info">Info</string>
<string name="profileWasNotFound">Het profiel dat in deze regel wordt gebruikt, lijkt niet meer te bestaan. De alfabetisch eerste is geselecteerd.</string>
<string name="enterText">Voer een tekst in.</string>
<string name="enterTitle">Voer een titel in.</string>
<string name="createNotification">Melding maken</string>
<string name="notificationCloseActionExplanation">Als u geen criteria opgeeft, worden met deze actie ALLE meldingen gesloten. Het is dus aan te raden om in ieder geval criteria te specificeren voor minimaal 1 van de toepassing, titel of tekst.</string>
<string name="closeNotifications">Melding(en) sluiten</string>
<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

@ -14,4 +14,6 @@
<color name="brightScreenTextColor">#FFFFFF</color>
<color name="darkScreenBackgroundColor">#444444</color>
<color name="darkScreenTextColor">#eeeeee</color>
<color name="red">#FF0000</color>
<color name="lightRed">#EC5959</color>
</resources>

View File

@ -70,7 +70,7 @@
<string name="end">End</string>
<string name="save">Save</string>
<string name="urlToTrigger">URL to trigger:</string>
<string name="urlLegend">Variables:\nYou can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text.\n\n[uniqueid] - Your device\'s unique id\n[serialnr] - Your device\'s serial number\n[latitude] - Your device\'s latitude\n[longitude] - Your device\'s longitude\n[phonenr] - Number of last incoming or outgoing call\n[d] - Day of the month, 2 digits with leading zeros\n[m] - Numeric representation of a month, with leading zeros\n[Y] - A full numeric representation of a year, 4 digits\n[h] - 12-hour format of an hour with leading zeros\n[H] - 24-hour format of an hour with leading zeros\n[i] - Minutes with leading zeros\n[s] - Seconds, with leading zeros\n[ms] - milliseconds\n[notificationTitle] - title of last notification\n[notificationText] - text of last notification</string>
<string name="urlLegend">Variables:\nYou can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text.\n\n[uniqueid] - Your device\'s unique id\n[serialnr] - Your device\'s serial number (&lt; Android 9)\n[latitude] - Your device\'s latitude\n[longitude] - Your device\'s longitude\n[phonenr] - Number of last incoming or outgoing call\n[d] - Day of the month, 2 digits with leading zeros\n[m] - Numeric representation of a month, with leading zeros\n[Y] - A full numeric representation of a year, 4 digits\n[h] - 12-hour format of an hour with leading zeros\n[H] - 24-hour format of an hour with leading zeros\n[i] - Minutes with leading zeros\n[s] - Seconds, with leading zeros\n[ms] - milliseconds\n[notificationTitle] - title of last notification\n[notificationText] - text of last notification</string>
<string name="wifi">wifi</string>
<string name="activating">Activating</string>
<string name="deactivating">Deactivating</string>
@ -496,7 +496,7 @@
<string name="startNewThreadForRuleExecution">Start new thread for rule activation.</string>
<string name="newThreadRules">New thread</string>
<string name="showIcon">Show icon</string>
<string name="showIconWhenServiceIsRunning">Show icon when service is running (hiding it only works below Android 7)</string>
<string name="showIconWhenServiceIsRunning">Show icon when service is running (hiding it only works below Android 7). If you\'re on a higher version, go to system settings, then Automation, then notifications and disable the \"Service notification\".</string>
<string name="ruleHistory">Rule history (most recent first):</string>
<string name="someOptionsNotAvailableYet">Some options are disabled as they cannot be used, yet. They will be introduced in a later program version.</string>
<string name="lockSoundChanges">Lock sound changes</string>
@ -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>
@ -631,7 +632,7 @@
<string name="selectSoundFile">Select sound file</string>
<string name="fileDoesNotExist">File does not exist.</string>
<string name="noFileManageInstalled">No file manager installed.</string>
<string name="shareConfigAndLogFilesWithDev">Share config and log files with developer (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Attach config and log files.</string>
<string name="shareConfigAndLogExplanation">This will start a new email with your config and log files attached as zip file. It will not be sent automatically, you still need to hit \"send\". You can also change the recipient to yourself for example.</string>
<string name="startAppChoiceNote">Here you have 2 general options:\n\n1. You can start a program by selecting an activity. Imagine this like preselecting a specific screen/window of an application. Keep in mind this may not always work. This is because the windows of an app might interact with each other, e.g. pass on parameters. When bluntly starting a specific screen that interaction has not happened and the window might close instantly (therefore it\'s never really shown). Try it nevertheless! You can enter an activity path manually, but it\'s recommended to use the \"Select\" button. If you decide to enter it manually enter the app\'s package name in the upper field and the full path of the activity in the lower one.\n\n2. Selection by action In contrast to selecting a specific window you can also start a program by an action. This is like shouting out \"I\'d would like xyz\" and if there\'s an app installed that can help you with that it will be started. A good example would be start browser - you might even have multiple installed (one is usually the default one). You need to enter this manually, PackageName is optional here. Keep in mind no variables will be resolved. If you want to start the camera for example using \"MediaStore.ACTION_IMAGE_CAPTURE\" will not work. You have to take a look at the Android documentation and use this variable\'s actual value instead which in this example would be \"android.media.action.IMAGE_CAPTURE\".</string>
<string name="errorRunningRule">There was an error running a rule.</string>
@ -743,7 +744,7 @@
<string name="profileActive">profile %1$s is active</string>
<string name="profileNotActive">profile %1$s is not active</string>
<string name="profileTriggerCheckSettings">If this checkbox is not disabled, it will only be checked if the selected profile has been the last one to be activated. It doesn\'t matter if any audio related settings have been changed externally. However if the checkbox is enabled, the current audio settings really need to be like defined in the profile. BEWARE: Checking the ringtone file is currently not supported, yet.</string>
<string name="ruleXIsUsingProfileY">Cannot delete this profile. Rule %s$1 is referencing profile %s$2.</string>
<string name="ruleXIsUsingProfileY">Cannot delete this profile. Rule %1$s is referencing profile %2$s.</string>
<string name="profileCouldNotBeDeleted">Profile could not be deleted.</string>
<string name="noRepetition">no repetition</string>
<string name="usingAuthentication">using authentication</string>
@ -755,4 +756,44 @@
<string name="pickActivityManually">Choose manually</string>
<string name="launcherOrManualExplanation">Easy mode: Automation can try to identify the launcher activity of the desired program automatically. Alternatively you can also pick one of the application\'s activities manually. What would you like?</string>
<string name="launcherNotFound">A launcher activity of this app could not be identified. You will have to pick one manually.</string>
<string name="createNotification">Create notification</string>
<string name="enterTitle">Enter a title.</string>
<string name="enterText">Enter a text.</string>
<string name="info">Info</string>
<string name="profileWasNotFound">The profile used in this rule doesn\'t seem to exist anymore. The alphabetically first one has been selected.</string>
<string name="notificationCloseActionExplanation">If you don\'t specify any criteria this action will close ALL notifications. So it\'s advised to at least specify criteria for at least 1 of application, title or text.</string>
<string name="closeNotifications">Close notification(s)</string>
<string name="comparisonCaseInsensitive">Comparisons are done case-INsensitive</string>
<string name="profileWarning">The settings you can adjust here, can cause that you don\'t notice certain things from your phone anymore. They may even silence your wakeup alarm. So whatever you do - it is recommended you test it.</string>
<string name="ifString">if</string>
<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

@ -1 +0,0 @@
* Fehler beim Setzen des Klingelmodus behoben

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

@ -20,6 +20,7 @@ Mögliche Auslöser:
* Telefongespräch im Gange
* Benachrichtigungen anderer Anwendungen
* Geräteausrichtung (Gyroskop)
* Profile aktiv oder nicht
Mögliche Aktionen:
* WLAN ein-/ausschalten
@ -40,6 +41,7 @@ Mögliche Aktionen:
* Bildschirmhelligkeit ändern
* SMS verschicken
* Sounddatei abspielen.
* Benachrichtigungen erstellen
Es ist ziemlich schwierig diese Anwendung über die vielen verschiedenen Geräte und Android Versionen am Laufen zu halten. Ich kann vieles im Emulator testen, aber eben nicht alles.
Wenn also eine bestimmte Funktion nicht so tut wie sie sollte - lassen Sie es mich wissen. Über die Jahre habe ich noch alle Fehler behoben, die mir vernünftig gemeldet wurden. Aber dafür bin ich auf Ihre Mithilfe angewiesen.

View File

@ -1 +1,11 @@
* New trigger: screen state (on/off)
* New action: Create notification
* New action: Close notification(s)
* 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

@ -20,6 +20,7 @@ Supported triggers:
* Phone call running
* Notifications of other apps
* Device orientation (gyroscope)
* Profile active or not
Supported actions:
* Change wifi state
@ -40,6 +41,7 @@ Supported actions:
* Change screen brightness
* Send text message
* Play sound file
* Create notifications
It's quite hard to keep this app working across the many different hardwares as well as the many changes Android undergoes over the versions. I can test it in the emulator, but that cannot show all bugs.
So if a certain feature is not working on your device - let me know. Over the years I have fixed almost all bugs that have been reasonably reported to me. But for that I'm dependend on your input.

View File

@ -1 +0,0 @@
* Se ha corregido un error en la configuración del modo de anillo

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

@ -20,6 +20,7 @@ Disparadores:
* Llamado de teléfono activo
* Notificaciónes de otras apps
* Orientación del dispositivo (giroscopio)
* Perfil activado o no
Aciónes:
* Pasar de wifi
@ -40,6 +41,7 @@ Aciónes:
* Cambiar luminosidad del monitor
* Enviar mensaje
* Tocar archivo sonido
* Crear notificaciones
Es muy dificil mantener esta applicación functionando en todos los hardwares y versiónes de Android. Puedo probrar mucho en el emulator, pero no puedo enviar todos los errores.
Si una función no funcióna - digame. En muchos años resolvaba la mayoria de los errores que los halladores me informaron bien. Pero dependo en su ayuda.

View File

@ -1 +0,0 @@
* Risolto un bug nell'impostazione della modalità anello

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

@ -20,6 +20,7 @@ Eventi supportati:
* Chiamata in esecuzione
* Notificazione di un altra applicazione
* Orientamento del dispositivo (giroscopio)
* Profilo attivo o meno
Azioni supportate:
* Cambia lo stato del wifi
@ -40,6 +41,7 @@ Azioni supportate:
* Cambia la luminosità dello schermo
* Manda un messaggio di testo
* Esegui un file musicale
* Creare notifiche
È piuttosto difficile mantere questa applicazione funzionante su tutti gli hardware esistenti ed includendo tutti i cambi che Android riceve fra una versione e l'altra. Posso effettuare tests nell'emulatore, ma non sarà possibile trovare tutti gli errori.
Pertanto, se una certa funzione non funziona sul tuo dispositivo - fammelo sapere. Nel corso degli anni ho potuto risolvere tutti gli errori che sono stati riportati in maniera ragionevole. Infatti, per questo, dipendo dalle informazioni condivise.

View File

@ -1 +0,0 @@
* Een bug opgelost in de ringmodus instellen

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

@ -22,6 +22,7 @@ Ondersteunde triggers:
* Lopend telefoongesprek
* Meldingen van andere apps
* Apparaat oriëntatie (gyroscoop)
* Profiel actief of niet
Ondersteunde acties:
* Wijzig wifi status
@ -42,6 +43,7 @@ Ondersteunde acties:
* Verander de helderheid van het scherm
* Verstuur tekstbericht
* Geluidsbestand afspelen
* Meldingen maken
Het is lastig om deze App werkend te houden over de vele verschillende hardware en de vele veranderingen die Android ondergaat in de loop der versies.
Ik test het in een emulator, maar dat kan niet alle bugs laten zien.

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