Compare commits

...

53 Commits

Author SHA1 Message Date
jens 0368b2a8c8 v118 2022-03-13 16:06:10 +01:00
jens 217f459833 nfc fix 2022-03-05 20:59:16 +01:00
jens 4c9e61618b profile delete bug fixed 2022-02-28 13:46:18 +01:00
jens e719114166 parallel rule execution 2022-02-27 18:01:54 +01:00
jens 0bd64e4a53 operator change 2022-02-22 23:08:25 +01:00
jens c569ab798c Android 11 2022-02-22 22:15:27 +01:00
jens 4e46878009 wrong field changed 2022-02-22 17:55:43 +01:00
jens 72ccdd99f9 logging 2022-02-20 18:57:13 +01:00
jens c9d7399068 logging 2022-02-14 20:06:20 +01:00
jens 275091f9d7 libs 2022-02-06 15:02:07 +01:00
jens bc31c9a4c8 translation 2022-02-05 13:47:43 +01:00
jens b02220609b show profile on main screen 2022-02-03 14:08:47 +01:00
jens da244d1bbe show profile on main screen 2022-02-03 14:05:42 +01:00
jens d402986dc3 ringtone 2022-02-03 13:41:05 +01:00
jens 85eee6c4da Android 11 2022-02-02 23:35:24 +01:00
jens 34883519e4 ringtone 2022-02-02 18:06:37 +01:00
jens 92e405d396 Media playing trigger 2022-01-30 22:19:08 +01:00
jens 1a8ce579a7 Media playing trigger 2022-01-30 22:08:55 +01:00
jens 5899dd86f5 media playback listener 2022-01-30 20:13:56 +01:00
jens 9387e8bdb2 media playback listener 2022-01-29 02:12:55 +01:00
jens 5ed024774e Control media playback 2022-01-27 23:05:54 +01:00
jens e76f9f69db control media playback 2022-01-27 11:35:46 +01:00
jens 0f1a12d28f control media playback 2022-01-27 11:34:04 +01:00
jens abaa961d3a Control media playback 2022-01-26 22:53:02 +01:00
jens 5f0eab5b30 control media playback 2022-01-26 21:40:29 +01:00
jens 92cb71ff2d Control media playback 2022-01-25 23:10:37 +01:00
jens 71adc83b39 control media playback 2022-01-25 18:08:46 +01:00
jens 88f4d65b19 control media playback 2022-01-24 20:13:35 +01:00
jens 0c5b4d3874 screen state trigger 2022-01-23 18:54:17 +01:00
jens d64ea8454e screen state trigger 2022-01-22 02:20:34 +01:00
jens 94f6418076 notification action 2022-01-21 21:52:27 +01:00
jens 83ee19b4fa ScreenStateReceiver 2022-01-21 20:57:42 +01:00
jens 5ed6097ed6 libs updated 2022-01-21 19:28:42 +01:00
jens 7e9d03104c Merge remote-tracking branch 'origin/development-stable' into development 2022-01-21 14:31:04 +01:00
jens 2e3e829abb Bugfix in sendTextMessage variable replacement 2022-01-21 13:56:21 +01:00
jens 06080bb456 Update 'app/src/main/java/com/jens/automation2/Actions.java' 2022-01-21 13:00:44 +01:00
jens a5fd23949d screen status trigger 2022-01-20 17:57:13 +01:00
jens 59c7a2d313 Notification channels 2022-01-17 20:09:46 +01:00
jens ec61a3ffa5 Service notification hint 2022-01-16 20:24:12 +01:00
jens a0c4cb7b6f notification action 2022-01-15 23:36:42 +01:00
jens 22899347a1 close notification action 2022-01-15 13:47:39 +01:00
jens 4b84a0c2f5 close notification action 2022-01-15 01:41:00 +01:00
jens 724192e80b close notification action 2022-01-14 19:57:32 +01:00
jens e6a7e2c5b5 ringmode bug fixed 2022-01-14 19:31:13 +01:00
jens e010e3392f ringmode bug fixed 2022-01-14 19:30:06 +01:00
jens f0853b3a30 close notification action 2022-01-11 17:27:07 +01:00
jens 98185a79df close notification action 2022-01-11 16:04:04 +01:00
jens 246a02371a notification action 2022-01-10 23:00:36 +01:00
jens 9b8ae2271b Notification action 2022-01-10 19:57:55 +01:00
jens b2cd3cf17c Merge remote-tracking branch 'origin/notification_action' into development 2022-01-10 19:33:24 +01:00
jens cf4ec286ae Notification action 2022-01-10 19:32:44 +01:00
jens 12f44aca8b notification action 2022-01-09 22:42:47 +01:00
jens 87edd595ba notification trigger 2022-01-09 15:22:03 +01:00
75 changed files with 3671 additions and 1598 deletions
+10 -9
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'
}
@@ -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"
}
],
+11 -1
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">
@@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@@ -21,8 +22,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@@ -312,19 +312,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@@ -351,7 +344,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@@ -433,7 +429,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class
// without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
@@ -441,7 +437,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@@ -476,66 +472,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
// Keep log of last x rule activations (Settings)
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true;
}
@@ -544,7 +531,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -553,13 +543,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule
break innerLoop; // we don't need to check the other triggers in the same rule
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@@ -608,186 +618,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -810,29 +640,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@@ -931,4 +738,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}
+11 -1
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">
@@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@@ -18,8 +19,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@@ -45,7 +45,7 @@ public class Rule implements Comparable<Rule>
{
this.lastExecution = lastExecution;
}
public boolean isRuleToggle()
{
return ruleToggle;
@@ -309,19 +309,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@@ -348,7 +341,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@@ -406,7 +402,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class
// without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
@@ -414,7 +410,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@@ -449,66 +445,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
// Keep log of last x rule activations (Settings)
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true;
}
@@ -517,7 +504,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -526,13 +516,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule
break innerLoop; // we don't need to check the other triggers in the same rule
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@@ -581,186 +591,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -783,29 +613,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@@ -904,4 +711,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}
+5 -1
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">
@@ -5,6 +5,7 @@ import static com.jens.automation2.Trigger.triggerParameter2Split;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@@ -21,8 +22,7 @@ import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static List<Rule> getRuleRunHistory()
@@ -312,19 +312,12 @@ public class Rule implements Comparable<Rule>
switch(action.getAction())
{
case setAirplaneMode:
return true;
case setBluetooth:
return true;
case setDataConnection:
return true;
case setDisplayRotation:
return true;
case setUsbTethering:
return true;
case setWifi:
return true;
case setWifiTethering:
return true;
case setBluetoothTethering:
return true;
default:
@@ -351,7 +344,10 @@ public class Rule implements Comparable<Rule>
if(applies(context))
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
}
@@ -433,7 +429,7 @@ public class Rule implements Comparable<Rule>
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
// without this line debugger will - for some reason - skip all breakpoints in this class
// without this line the debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
@@ -441,7 +437,7 @@ public class Rule implements Comparable<Rule>
Looper.prepare();
setLastExecution(Calendar.getInstance());
wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]);
wasActivated = activateInternally((AutomationService)params[0]);
return null;
}
@@ -476,66 +472,57 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", message, 2);
// Keep log of last x rule activations (Settings)
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
Miscellaneous.logEvent("e", "RuleExecution", "Error running action of rule " + Rule.this.getName() + ": " + Log.getStackTraceString(e), 1);
}
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
// Keep log of last x rule activations (Settings)
try
{
Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization
Rule.lastActivatedRuleActivationTime = new Date();
while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize)
ruleRunHistory.remove(ruleRunHistory.size()-1);
String history = "";
for(Rule rule : ruleRunHistory)
history += rule.getName() + ", ";
if(history.length() > 0)
history = history.substring(0, history.length()-2);
Miscellaneous.logEvent("i", "Rule history", "Most recent first: " + history, 4);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Rule history error", Log.getStackTraceString(e), 3);
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
return true;
}
@@ -544,7 +531,10 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
task.execute(automationService, force);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -553,13 +543,33 @@ public class Rule implements Comparable<Rule>
for(Rule oneRule : ruleCollection)
{
innerloop:
innerLoop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == triggerType)
if(oneTrigger.getTriggerType().equals(triggerType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other triggers in the same rule
break innerLoop; // we don't need to check the other triggers in the same rule
}
}
}
return ruleCandidates;
}
public static ArrayList<Rule> findRuleCandidates(Action.Action_Enum actionType)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction().equals(actionType))
{
ruleCandidates.add(oneRule);
break innerloop; // we don't need to check the other actions in the same rule
}
}
}
@@ -608,186 +618,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByTimeFrame(TimeFrame searchTimeFrame, boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(int i=0; i<ruleCollection.size(); i++)
{
innerloop:
for(int j=0; j<ruleCollection.get(i).getTriggerSet().size(); j++)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
if(ruleCollection.get(i).getTriggerSet().get(j).getTimeFrame().equals(searchTimeFrame) && ruleCollection.get(i).getTriggerSet().get(j).getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(ruleCollection.get(i));
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByTime(Time searchTime)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching for rules with TimeFrame with time " + searchTime.toString() + ". RuleCollection-Size: " + String.valueOf(ruleCollection.size()), 3);;
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.timeFrame)
{
Miscellaneous.logEvent("i", "RuleSearch", "Searching interval: " + oneTrigger.getTimeFrame().getTriggerTimeStart().toString() + " to " + oneTrigger.getTimeFrame().getTriggerTimeStop().toString(), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval start: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "search time: " + String.valueOf(searchTime.getTime()), 5);
Miscellaneous.logEvent("i", "RuleSearch", "interval stop: " + String.valueOf(oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()), 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() > oneTrigger.getTimeFrame().getTriggerTimeStop().getTime())
{
Miscellaneous.logEvent("i", "Timeframe search", "Rule (" + oneRule.getName() + ") stretches over midnight.", 5);
if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() || searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
else if(oneTrigger.getTimeFrame().getTriggerTimeStart().getTime() <= searchTime.getTime() && searchTime.getTime() <= oneTrigger.getTimeFrame().getTriggerTimeStop().getTime()+20000) //add 20 seconds because of delay
{
Miscellaneous.logEvent("i", "RuleSearch", "Rule found (" + oneRule.getName() + ") with TimeFrame with time " + searchTime.toString(), 3);
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
Miscellaneous.logEvent("i", "RuleSearch", String.valueOf(ruleCandidates.size()) + " Rule(s) found with TimeFrame with time " + searchTime.toString(), 3);
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByCharging(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.charging)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByUsbHost(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.usb_host_connection)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //if the poi is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByAirplaneMode(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.airplaneMode)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByRoaming(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.roaming)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
/*public static ArrayList<Rule> findRuleCandidatesByPhoneCall(String direction)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.phoneCall)
{
String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split);
if(elements[1].equals(Trigger.triggerPhoneCallDirectionAny) || elements[1].equals(direction))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByPoi(PointOfInterest searchPoi)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -810,29 +640,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
@@ -931,4 +738,15 @@ public class Rule implements Comparable<Rule>
{
return ActivityPermissions.havePermissionsForRule(this, Miscellaneous.getAnyContext());
}
public static Rule getByName(String ruleName)
{
for(Rule r : Rule.getRuleCollection())
{
if(r.getName().equals(ruleName))
return r;
}
return null;
}
}
+202 -120
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,134 +164,194 @@ public class Action
{
StringBuilder returnString = new StringBuilder();
switch(getAction())
try
{
case setWifi:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOff));
break;
case setBluetooth:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOff));
break;
case setUsbTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOff));
break;
case setWifiTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOff));
break;
case setBluetoothTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOff));
break;
case setDisplayRotation:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionEnableScreenRotation));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionDisableScreenRotation));
break;
case setAirplaneMode:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOff));
break;
case setDataConnection:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOff));
break;
case startOtherActivity:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.startOtherActivity));
break;
case triggerUrl:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTriggerUrl));
break;
case speakText:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSpeakText));
break;
case playMusic:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionPlayMusic));
break;
case sendTextMessage:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendTextMessage));
break;
case turnScreenOnOrOff:
if (getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOff));
break;
case playSound:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.playSound));
break;
case changeSoundProfile:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionChangeSoundProfile));
break;
case waitBeforeNextAction:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.waitBeforeNextAction));
break;
case setScreenBrightness:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.setScreenBrightness));
break;
default:
returnString.append(action.toString());
}
if(this.getAction().equals(Action_Enum.triggerUrl))
{
String[] components = parameter2.split(";");
if(components.length >= 3)
switch (getAction())
{
returnString.append(": " + components[2]);
if(parameter1)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + ".");
case setWifi:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOff));
break;
case setBluetooth:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOff));
break;
case setUsbTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOff));
break;
case setWifiTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOff));
break;
case setBluetoothTethering:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOff));
break;
case setDisplayRotation:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionEnableScreenRotation));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionDisableScreenRotation));
break;
case setAirplaneMode:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOff));
break;
case setDataConnection:
if (this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOff));
break;
case startOtherActivity:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.startOtherActivity));
break;
case triggerUrl:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTriggerUrl));
break;
case speakText:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSpeakText));
break;
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;
case turnScreenOnOrOff:
if (getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOff));
break;
case playSound:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.playSound));
break;
case changeSoundProfile:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionChangeSoundProfile));
break;
case waitBeforeNextAction:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.waitBeforeNextAction));
break;
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());
}
else
returnString.append(": " + components[0]);
}
else if(this.getAction().equals(Action_Enum.startOtherActivity))
{
returnString.append(": " + parameter2.replace(Action.intentPairSeperator, "/"));
}
else if(this.getAction().equals(Action_Enum.sendTextMessage))
{
String[] components = parameter2.split(Actions.smsSeparator);
if(components.length >= 2)
if (this.getAction().equals(Action_Enum.triggerUrl))
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.toNumber) + " " + components[0]);
String[] components = parameter2.split(";");
if (components.length >= 3)
{
returnString.append(": " + components[2]);
returnString.append(". " + Miscellaneous.getAnyContext().getResources().getString(R.string.message) + ": " + components[1]);
if (parameter1)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + ".");
}
else
returnString.append(": " + components[0]);
}
else if (this.getAction().equals(Action_Enum.startOtherActivity))
{
returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/"));
}
else if (this.getAction().equals(Action_Enum.sendTextMessage))
{
String[] components = parameter2.split(Actions.smsSeparator);
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))
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.to) + " ");
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
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, "; "));
}
else if(this.getAction().equals(Action_Enum.setScreenBrightness))
catch (Exception e)
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.to) + " ");
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) + "%");
returnString.append(": " + Miscellaneous.getAnyContext().getResources().getString(R.string.error));
}
else
if (parameter2 != null && parameter2.length() > 0)
returnString.append(": " + parameter2);
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;
@@ -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);
@@ -694,7 +800,7 @@ public class Actions
// am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
// }
// else
myAudioManager.setRingerMode(desiredSoundSetting);
myAudioManager.setRingerMode(desiredSoundSetting);
}
private static String getIPAddressUsb(final boolean useIPv4)
@@ -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;
@@ -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,32 +306,33 @@ 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());
/*
Without root the zip file in the cache directory is not directly accessible.
But have to route it through this content provider crap.
*/
/*
Without root the zip file in the cache directory is not directly accessible.
But have to route it through this content provider crap.
*/
String subject = "Automation logs";
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();
}
}
@@ -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;
}
@@ -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;
@@ -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();
}
@@ -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();
}
}
}
@@ -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;
}
}
@@ -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();
}
});
}
}
@@ -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)
{
@@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -12,6 +13,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.view.MotionEvent;
@@ -30,6 +32,8 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import java.util.ArrayList;
@@ -54,6 +58,8 @@ public class ActivityManageActionStartActivity extends Activity
final String urlShowExamples = "https://server47.de/automation/examples_startProgram.html";
final static String startByActivityString = "0";
final static String startByBroadcastString = "1";
final static int requestCodeForRequestQueryAllPackagesPermission = 4711;
private class CustomPackageInfo extends PackageInfo implements Comparable<CustomPackageInfo>
{
@@ -331,6 +337,13 @@ public class ActivityManageActionStartActivity extends Activity
return alertDialog;
}
void getAppList()
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
@@ -364,9 +377,13 @@ public class ActivityManageActionStartActivity extends Activity
@Override
public void onClick(View v)
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && targetSdkVersion >= 30)
{
requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission);
}
else
getAppList();
}
});
@@ -387,9 +404,9 @@ public class ActivityManageActionStartActivity extends Activity
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(Action.intentPairSeperator))
else if(etParameterName.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(";"))
@@ -403,9 +420,9 @@ public class ActivityManageActionStartActivity extends Activity
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(Action.intentPairSeperator))
else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(";"))
@@ -414,7 +431,7 @@ public class ActivityManageActionStartActivity extends Activity
return;
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeperator + etParameterName.getText().toString() + Action.intentPairSeperator + etParameterValue.getText().toString();
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
spinnerParameterType.setSelection(0);
@@ -661,4 +678,22 @@ public class ActivityManageActionStartActivity extends Activity
getActionStartActivityDialog1Application().show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == requestCodeForRequestQueryAllPackagesPermission)
{
for(int i = 0; i < permissions.length; i++)
{
if(permissions[i].equals(Manifest.permission.QUERY_ALL_PACKAGES) && grantResults[i] == PackageManager.PERMISSION_GRANTED)
{
getAppList();
break;
}
}
}
}
}
@@ -12,6 +12,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
@@ -83,17 +84,17 @@ public class ActivityManagePoi extends Activity
bSavePoi = (Button)findViewById(R.id.bSavePoi);
bSavePoi.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
hideKeyboard();
@Override
public void onClick(View v)
{
hideKeyboard();
if(ActivityMainPoi.poiToEdit == null)
createPoi();
else
changePoi();
}
});
if(ActivityMainPoi.poiToEdit == null)
createPoi();
else
changePoi();
}
});
ibShowOnMap.setOnClickListener(new OnClickListener()
{
@@ -136,42 +137,45 @@ public class ActivityManagePoi extends Activity
private void getLocation()
{
Criteria critNetwork = new Criteria();
critNetwork.setPowerRequirement(Criteria.POWER_LOW);
critNetwork.setAltitudeRequired(false);
critNetwork.setSpeedRequired(false);
critNetwork.setBearingRequired(false);
critNetwork.setCostAllowed(false);
critNetwork.setAccuracy(Criteria.ACCURACY_COARSE);
Criteria criteriaNetwork = new Criteria();
criteriaNetwork.setPowerRequirement(Criteria.POWER_LOW);
criteriaNetwork.setAltitudeRequired(false);
criteriaNetwork.setSpeedRequired(false);
criteriaNetwork.setBearingRequired(false);
criteriaNetwork.setCostAllowed(false);
criteriaNetwork.setAccuracy(Criteria.ACCURACY_COARSE);
Criteria criteriaGps = new Criteria();
criteriaGps.setAltitudeRequired(false);
criteriaGps.setSpeedRequired(false);
criteriaGps.setBearingRequired(false);
criteriaGps.setCostAllowed(true);
criteriaGps.setAccuracy(Criteria.ACCURACY_FINE);
Criteria critGps = new Criteria();
critGps.setAltitudeRequired(false);
critGps.setSpeedRequired(false);
critGps.setBearingRequired(false);
critGps.setCostAllowed(true);
critGps.setAccuracy(Criteria.ACCURACY_FINE);
String provider1 = myLocationManager.getBestProvider(critNetwork, true);
String provider2 = myLocationManager.getBestProvider(critGps, true);
String provider1 = myLocationManager.getBestProvider(criteriaNetwork, true);
String provider2 = myLocationManager.getBestProvider(criteriaGps, true);
// String provider3 = myLocationManager.getProvider("wifi");
if(provider1 == null | provider2 == null)
if(provider1 == null || provider2 == null)
{
Toast.makeText(this, getResources().getString(R.string.logNoSuitableProvider), Toast.LENGTH_LONG).show();
return;
}
else
{
if(provider1.equals(provider2))
Miscellaneous.logEvent("i", "POI Manager", "Both location providers are equal. Only one will be used.", 4);
locationSearchStart = Calendar.getInstance();
startTimeout();
if(!Settings.privacyLocationing || !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
if(!Settings.privacyLocationing && !ConnectivityReceiver.isDataConnectionAvailable(Miscellaneous.getAnyContext()) && !provider1.equals(provider2))
{
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider1, 3);
myLocationManager.requestLocationUpdates(provider1, 500, Settings.satisfactoryAccuracyNetwork, myLocationListenerNetwork);
}
else
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location query because private locationing is active.", 4);
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location.", 4);
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider2, 3);
myLocationManager.requestLocationUpdates(provider2, 500, Settings.satisfactoryAccuracyGps, myLocationListenerGps);
@@ -310,7 +314,21 @@ public class ActivityManagePoi extends Activity
public void onClick(DialogInterface dialog, int which)
{
progressDialog = ProgressDialog.show(ActivityManagePoi.this, "", getResources().getString(R.string.gettingPosition), true, true);
getLocation();
if(Build.VERSION.SDK_INT >= 31)
{
AlertDialog dia = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.locationNotWorkingOn12), ActivityManagePoi.this);
dia.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
getLocation();
}
});
dia.show();
}
else
getLocation();
}
};
alertDialogBuilder.setMessage(text).setPositiveButton("Ok", dialogClickListener);
@@ -44,6 +44,8 @@ public class ActivityManageProfile extends Activity
Button bChangeSoundIncomingCalls, bChangeSoundNotifications, bSaveProfile;
TextView tvIncomingCallsRingtone, tvNotificationsRingtone;
EditText etName;
boolean guiUpdate = false;
File incomingCallsRingtone = null, notificationsRingtone = null;
@@ -368,6 +370,8 @@ public class ActivityManageProfile extends Activity
public void editProfile(Profile profileToEdit)
{
guiUpdate = true;
etName.setText(ActivityMainProfiles.profileToEdit.getName());
checkBoxChangeSoundMode.setChecked(ActivityMainProfiles.profileToEdit.getChangeSoundMode());
checkBoxChangeDnd.setChecked(ActivityMainProfiles.profileToEdit.getChangeDndMode());
@@ -393,6 +397,8 @@ public class ActivityManageProfile extends Activity
setIncomingCallsRingtone(ActivityMainProfiles.profileToEdit.getIncomingCallsRingtone());
setNotificationsRingtone(ActivityMainProfiles.profileToEdit.getNotificationRingtone());
guiUpdate = false;
}
private boolean loadFormValuesToVariable()
@@ -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);
@@ -1904,8 +2060,8 @@ public class ActivityManageRule extends Activity
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
}
protected void refreshTriggerList()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update TriggerListView", 4);
@@ -1951,4 +2107,4 @@ public class ActivityManageRule extends Activity
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
}
@@ -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++)
@@ -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)
@@ -353,14 +353,21 @@ public class ActivityPermissions extends Activity
if(!havePermission(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, workingContext))
addToArrayListUnique(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, requiredPermissions);
for(Profile p : Profile.getProfileCollection())
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
}
if (!onlyGeneral)
{
for (Rule rule : Rule.getRuleCollection())
{
for (String singlePermission : getPermissionsForRule(rule))
{
if (!havePermission(singlePermission, workingContext))
{
if(
if (
singlePermission.equalsIgnoreCase(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
||
@@ -372,14 +379,15 @@ public class ActivityPermissions extends Activity
if (!Miscellaneous.googleToBlameForLocation(true))
addToArrayListUnique(singlePermission, requiredPermissions);
}
else if(singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection))
else if (singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection))
{
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
if (!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
addToArrayListUnique(singlePermission, requiredPermissions);
}
else
addToArrayListUnique(singlePermission, requiredPermissions);
}
}
}
}
@@ -518,6 +526,9 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.MODIFY_AUDIO_SETTINGS, requiredPermissions);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
addToArrayListUnique(Manifest.permission.ACCESS_NOTIFICATION_POLICY, requiredPermissions);
Profile targetProfile = Profile.getByName(action.getParameter2());
if(targetProfile.changeIncomingCallsRingtone || targetProfile.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case disableScreenRotation:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@@ -527,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]
@@ -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,10 +128,15 @@ 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,7 +218,14 @@ public class AutomationService extends Service implements OnInitListener
// Actions.setData(true);
// ********** Test area **********
return START_STICKY;
/*
On normal phones the app is supposed to automatically restart in case of any problems.
In the emulator we want it to stop to be able to better pinpoint the root cause.
*/
if(Miscellaneous.isAndroidEmulator())
return START_NOT_STICKY;
else
return START_STICKY;
}
else
{
@@ -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));
@@ -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;
@@ -631,27 +636,43 @@ public class Miscellaneous extends Service
if(source.contains("[notificationTitle]"))
{
String notificationTitle = NotificationListener.getLastNotification().getTitle();
if(NotificationListener.getLastNotification() != null)
{
String notificationTitle = NotificationListener.getLastNotification().getTitle();
if(notificationTitle != null && notificationTitle.length() > 0)
source = source.replace("[notificationTitle]", notificationTitle);
if (notificationTitle != null && notificationTitle.length() > 0)
source = source.replace("[notificationTitle]", notificationTitle);
else
{
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationTitle was empty.", 3);
}
}
else
{
source = source.replace("notificationTitle unknown", notificationTitle);
Miscellaneous.logEvent("w", "Variable replacement", "notificationTitle was empty.", 3);
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
if(source.contains("[notificationText]"))
{
String notificationText = NotificationListener.getLastNotification().getText();
if(NotificationListener.getLastNotification() != null)
{
String notificationText = NotificationListener.getLastNotification().getText();
if(notificationText != null && notificationText.length() > 0)
source = source.replace("[notificationText]", notificationText);
if (notificationText != null && notificationText.length() > 0)
source = source.replace("[notificationText]", notificationText);
else
{
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationText was empty.", 3);
}
}
else
{
source = source.replace("notificationText unknown", notificationText);
Miscellaneous.logEvent("w", "Variable replacement", "notificationText was empty.", 3);
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
@@ -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);
builder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
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;
}
}
@@ -4,10 +4,12 @@ import android.app.NotificationManager;
import android.content.ContentValues;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
@@ -306,29 +308,31 @@ public class Profile implements Comparable<Profile>
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, ringtoneFile.getAbsolutePath());
// values.put(MediaStore.MediaColumns.TITLE, context.getResources().getString(R.string.app_name) + " ringtone");
// values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName().replace(".mp3", "").replace(".", ""));
values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName());
// values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, ringtoneFile.length());
// values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, ringtoneType == RingtoneManager.TYPE_RINGTONE);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, ringtoneType == RingtoneManager.TYPE_NOTIFICATION);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if(existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
Uri newRingTone = context.getContentResolver().insert(existingRingTone, values);
try
{
Uri newRingTone = null;
//TODO: This part needs to be made compatible with Android 11 and above.
if(Build.VERSION.SDK_INT > 30)
{
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if (existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
newRingTone = context.getContentResolver().insert(existingRingTone, values);
}
RingtoneManager.setActualDefaultRingtoneUri(context, ringtoneType, newRingTone);
Miscellaneous.logEvent("i", "Profile", "Ringtone set to: " + newRingTone.toString(), 1);
// Ringtone tone = RingtoneManager.getRingtone(context, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
// tone.play();
return true;
}
catch (Throwable t)
@@ -454,29 +458,17 @@ public class Profile implements Comparable<Profile>
public boolean delete(Context context)
{
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.profileActive))
Rule usingRule = this.isInUseByRules();
if(usingRule != null)
{
for (Rule rule : Rule.findRuleCandidatesByTriggerProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
{
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), usingRule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
else
{
profileCollection.remove(this);
return XmlFileInterface.writeFile();
}
return false;
}
private boolean plausibilityCheck()
@@ -604,65 +596,107 @@ public class Profile implements Comparable<Profile>
try
{
AudioManager am = (AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE);
NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(changeSoundMode)
if (changeSoundMode)
{
if(am.getRingerMode() != soundMode)
if (am.getRingerMode() != soundMode)
return false;
}
if(changeDndMode && Build.VERSION.SDK_INT >= 23)
if (changeDndMode && Build.VERSION.SDK_INT >= 23)
{
if(mNotificationManager.getCurrentInterruptionFilter() != dndMode)
if (mNotificationManager.getCurrentInterruptionFilter() != dndMode)
return false;
}
if(changeVolumeMusicVideoGameMedia)
if (changeVolumeMusicVideoGameMedia)
{
if(am.getStreamVolume(AudioManager.STREAM_MUSIC) != volumeMusic)
if (am.getStreamVolume(AudioManager.STREAM_MUSIC) != volumeMusic)
return false;
}
if(changeVolumeNotifications)
if (changeVolumeNotifications)
{
if(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != volumeNotifications)
if (am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != volumeNotifications)
return false;
}
if(changeVolumeAlarms)
if (changeVolumeAlarms)
{
if(am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
if (am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
return false;
}
// if(changeIncomingCallsRingtone)
// {
// if (incomingCallsRingtone != null)
// {
// applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
// }
// }
if(changeVibrateWhenRinging)
/*if (changeIncomingCallsRingtone)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if (incomingCallsRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE);
if (ringtone_uri != null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
Ringtone currentRingtone = RingtoneManager.getRingtone(context, ringtone_uri);
String title = currentRingtone.getTitle(context);
*//* Ringtone desiredRingtone = RingtoneManager.getRingtone(context, Uri.fromFile(notificationRingtone));
boolean result = currentRingtone.equals(desiredRingtone);*//*
Uri desired_ringtone = MediaStore.Audio.Media.getContentUriForPath(incomingCallsRingtone.getAbsolutePath());
// File currentRingtoneFile = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(ringtone_uri.getPath());
String desiredChecksum = Miscellaneous.checksumSha(incomingCallsRingtone.getAbsolutePath());
if (!currentChecksum.equals(desiredChecksum))
return false;
}
}
}*/
if (changeVibrateWhenRinging)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), "vibrate_when_ringing");
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
if (currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
return false;
}
else
{
int currentSetting = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
if (currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
return false;
}
}
// if(changeNotificationRingtone)
// if(notificationRingtone != null)
// applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
/*if (changeNotificationRingtone)
{
if (notificationRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION);
if (ringtone_uri == null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
File currentRingtone = new File(Settings.System.DEFAULT_NOTIFICATION_URI.getPath());
// File currentRingtone = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(currentRingtone.getAbsolutePath());
String desiredChecksum = Miscellaneous.checksumSha(notificationRingtone.getAbsolutePath());
if(!currentChecksum.equals(desiredChecksum))
return false;
}
else
return false;
}
}*/
if(changeScreenLockUnlockSound)
{
@@ -730,4 +764,11 @@ public class Profile implements Comparable<Profile>
return this.oldName;
}
public static Profile getLastActivatedProfile()
{
if(Profile.profileActivationHistory != null && Profile.profileActivationHistory.size() > 0)
return Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
else
return null;
}
}
@@ -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))
@@ -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);
@@ -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();